原文地址:XHR progress and rich file upload feedback
系列地址:颠覆网络35天
====================================
这个演示由Olli Pettay (smaug)和Austin King制作。
文件上传在今天的互联网中还是一个用户体验不那么好的功能特性。很多站点使用Flash或者单独构建客户端来完成文件上传的功能。
Firefox 3.5提供了一个稍好的进度条功能,也许可以完善一下这个用户体验。很多开发人员可能并不知道他们可以使用Firefox的文件对象(nsIDOMFile)和XMLHttpRequest一起来构建完整的文件上传功能。这个演示的目的就是为大家演示一下如何使用他们来打造一个体验良好的文件上传组件,可以显示上传的进度,并且可以同时上传多个文件。
进度条
在应用程序中向用户显示程序的进度总是一个非常好的体验,可以告诉用户你的应用正在努力工作完成他们的要求,并且能显示工作进行到大概什么样的一个程度。主要的两种进度反馈包括:
- 不确定进度 ── 显示正在发生的某些活动
- 确定性进度 ── 我已经完成40%了、42%了……等等
确定什么进度什么?看演示吧
我们制作了一个简单的文件上传/下载页面用来演示进度条:
演示放在mozilla.pettay.fi,并且需要Firefox 3.5 beta4或者更高版本。他演示了如何同时上传多个文件,而且不用通过提交表单的方式或者不离开当前页面。针对每个文件的上传/下载,我们显示当前的速度、完成的百分比和已经传输的字节数。我们会在后面介绍几个关键的地方,现在可以先试试这个演示,也可以查看整个演示的代码。
页面包括两个HTML输入控件,一个是type="file",另一个type="button"。 但是表单从来没有被真正提交,相反我们为按钮添加onclick事件监听:
<input type=“file” id=“file”> <input type=“button” onclick=“startXHR();” value=“Upload file using XHR”>
在startXHR函数中,我们生成XMLHttpRequest对象然后添加时间处理函数监听XHR对象的‘progress’事件──Firefox 3.5新加入的。使用这个进度事件ProgressEvent的lengthComputable属性,我们可以知道处理的是不确定进度还是确定性进度。该事件对象还会告诉我们已经读取的和全部的字节数。
var xhr = new XMLHttpRequest(); xhr.onprogress = function(evt) { if (evt.lengthComputable) { evt.target.curLoad = evt.loaded;target.log.parentNode.parentNode.previousSibling.textContent = Number(evt.loaded/k).toFixed() + “/”+ Number(evt.total/k).toFixed() + “kB”; } if (evt.lengthComputable) { var loaded = (evt.loaded / evt.total); if (loaded < 1) { var newW = loaded * width; if (newW < 10) newW = 10; evt.target.log.style.width = newW + “px”; } } };
现在我们需要的是传送点数据了~我们直接从输入中得到文件内容:
var files = document.getElementById(“file”).files; if (files) { var file = files.item(0); xhr.sendAsBinary(file.getAsBinary());
最后一步就是开始请求:
xxhr.open(“POST”, “cgi-bin/posthandler.pl”); xhr.overrideMimeType(‘text/plain; charset=x-user-defined-binary’); xhr.sendAsBinary(file.getAsBinary());
注意XMLHttpRequest对象上sendAsBinary方法的使用,以及文件对象的getAsBinary方法。从Firefox 3开始,您可以直接在客户端获得文件内容。这确实跟传统浏览器处理文件的方法大大不同了。这些操作是W3C 文件上传草案的内容。
nsIDOMFile还提供一个类似的方法叫做getAsText,可以直接从文件中提取内容并返回DOMString(字符串对象),可以进一步进行截取、显示等操作。
这里是一个代码示例,不过没有在这个演示中使用:
file.getAsText(“utf8″);
想了解全部代码细节,请查看演示页面并看该页面的代码。
用户界面上的操作反馈
把系统的一些操作反馈信息返回给用户能够改进提升系统的认知能力。当然不是所有的进度都能够显示出来,那最小的程度,我们可以显示一个不确定进度,显示正在发生什么的提示等等。
在文件上传和下载过程中(假设服务器给我们提供Content-Length),我们确实需要知道传输的字节数。Firefox 3.5支持进度事件,所以我们可以显示确切的上传和下载进度。
传统的XMLHttpRequest很难获取确定的进度信息。理论上,你可以挂上回调函数然后持续监视状态代码更新和一些上下文的消息更新等等,但是实际做起来,这些代码和消息不是很有用。在过去,如果确定进度很重要必须要显示的话,智能开启第二个XHR请求去查询进度情况。
进度事件内部
W3C目前已经有进度事件 1.0的草案,我们在Firefox 3.5中实现也是依据这个草案。Firefox添加的进度事件包括全新的progress事件和loadstart事件,其他的还包括:error、abort和load。
进度事件给我们提供下列属性:
- lengthComputable ─ true或者false,表示请求数据的大小是否已知?
- loaded ─ 目前接收到的字节数
- total ─ 整个请求中期望传输的字节数
契约
当你查看进度事件的属性时,有一些规则需要注意:
- 当lengthComputable为false时,total属性值为0。
- loadstart事件只会被激发一次。
- 在loadstart之后,进度事件可能被激发0次或多次。
就是这样了。快去使用Firefox 3.5提供的特性构建更好的文件上传体验吧~

Comments (2)
没装,。。。。还在用3.0
非常棒!非常有用的資料~