未来Web应用开发探秘:File API

回想一下过去那些糟糕的日子:要上传文件到一个网站需要在一个file input上点击“浏览”按钮,然后导航到这个文件所在的文件夹,再点击“打开”,如果要上传多个文件,需要对每一个文件重复上面的步骤!有了File API,那些日子将一去不复返了。

File API是什么?

File API是一套强大的API,它可以让开发者处理来自于用户文件系统的文件,并且可以让开发者在Web应用程序里使用这些文件,所有这些事情都在本地处理,不需要在服务器上处理。

File API能做什么?

在很多场景下,许多应用程序中,File API都是很有用的。最明显的用途就是使用Drag和Drop API在drop事件上访问文件的,来支持拖放式上传文件(比如image)。当用户drop文件的时候,你可以把他们转换成一个data URL,马上给用户提供反馈,同时可以用异步的方式把要上传的image的缩略图展示给用户,这可以给用户提供一个无缝的交互体验。

几个例子:

我们收集了一个炫耀File API的例子(http://www.thecssninja.com/demo/crystalball/),这个Demo可以在Firefox3.6和Chrome 6 dev版上正常运行。从你的桌面上拖放任意文件到这个Demo中,看看会发生什么......

◆一个图片编辑器——http://demos.hacks.mozilla.org/openweb/imageUploader

◆box.net最近添加了对拖放式上传文件的支持—— box.net

◆font dragr – 测试自定义字体的Web应用程序* – http://fontdragr.com

如何使用File API

使用File API,你有两种方法可以访问一个文件并进行操作。第一种方法是通过file input和文件属性。

document.getElementById("fileinput").files  


 

上面的代码访问了FileList对象,它是一个包含多个文件的序列数组。每个文件都有几个属性可用,例如name, size和type

访问一个文件的另一种方法是通过Drag和Drop API,在dataTransfer对象上,也包含一个FileList对象,dataTransfer对象在DnD API的drop事件上可用。

event.dataTransfer.files  


 

这两种方法都返回同一个序列数组。拖放多个文件可以被处理,并且如果file input有multiple属性,它也可以处理多个文件。

FileReader

为了用FileList对象来做一些事情,在无需服务器参与的情况下操作文件来显示给用户,我们可以使用FileReader对象。它是异步处理的,所以只要不锁定浏览器的UI,它就一直在处理文件。

var reader = new FileReader();  


       



    reader.onload = function (evt) {  




        // do something with the file once it's loaded  




        var data = evt.target.result, // file is stored in the result attribute;  




              img = document.createElement("img");  



       


        img.src = data;  



        document.getElementsByTagName("body").appendChild(img);  



    }  


    reader.readAsDataURL(file); 

 

上面的代码我们创建了一个新的FileReader对象,然后我们初始化了我们的onload函数,所以只要文件载入了内存,我们就可以操作这个文件了。最后一个函数告诉reader,我们想用这个文件做什么。在我们的实例中,是返回一个DataURL。还有两个其他的方法可以使用,它们是:

readAsText() 和readAsBinary()

在onload事件的内部,我们创建了一个新的image元素,设置它的source设置成result属性的值,然后把它附加到document body上。这立刻会把这个image显示给用户。

处理大文件——File URL

在前面的例子里,我已经向你展示了如何载入一个文件,然后把它展示给用户。所有这些方法本质上都是用readAsDataURL/Binary/Text等函数创建一个文件的拷贝,然后把它载入你的可用内存中。当用户载入了许多文件,或非常大的文件的时候,就会产生问题。比如说,用户要拖动一个200MB的视频或者它们拖入了许多的视频!这将会产生大量的数据,它们都需要载入内存,这会使任何机器突然停止响应,更可能的结果是使浏览器崩溃。值得庆幸的是File API的创建者和贡献者已经想到了这个问题,并且在FileReader对象上添加了一个非常有用的属性——url。

URL

URL是一个随机产生的唯一字符串,它映射到你的硬盘上的一个物理文件。这是很有用的,因为这个唯一的字符串可以在html文档中使用。例如有一个image。把这个image的source设置成File API生成的唯一字符串,不需要把它载入内存,就可以让你把这个image显示给用户。

<img src="moz-filedata:8616e48b-2a2b-418d-9ad4-5669858cf038" /> 


 

上面的例子展示了在Firefox 4中使用的url属性,image的source应该是什么样子的。

想象一下这个场景。在你的图片网站上,你有一个image uploader,用户在他们的图片里拖动了一些文件,要drop的那些图片显示成了一个漂亮的缩小版本的网格,但是用户发现了一个问题,认识到那些image中,有一个需要修整一下。他们在一个图片编辑器中打开这个文件,做了一些修整,回到Web应用程序并点击上传按钮。使用url的好处是改变的文件也可以被上传,因为它实时的链接到文件系统中的物理image,所以无须用户重新把它们添加到上传列表中。

到现在为止,Firefox 4是唯一一个支持url属性的浏览器,即便如此,它还存在一个bug:唯一字符串只能显示通过file input载入的image。无法显示通过drop事件载入的image。但是,在Firefox 4的稳定版本中,这个bug应该已经被修复了。

看看这个Firefox 4中的Demo(http://www.thecssninja.com/demo/crystalball/fileurl.html),它使用一个file input载入文件,使用了url属性。

// Code showing url  



var droppedFileURL = file.url;  



...  


img.src = droppedFileURL; 

上面的代码很简单。并不需要附加一个事件来把image载入内存,然后把它转换成一个data URL,我们只需要简单的遍历文件,访问file对象的url属性,然后用它设置我们的image的source。对于开发者来说,工作量减轻了,同时用户计算机的压力也减轻了。这是一个两全其美的方法。

向何处前进

在写这篇文章的时候,只有两个浏览器支持File API:Firefox 3.6和Chrome 6,它们分别在不同程度上支持了File API规范。

相关推荐