实现将文件从桌面直接拖放到浏览器中是web应用开发的终极目标之一,本文作为接下来四篇文章的第一篇将解决以下问题:
1.实现将一个文件拖放到一个页面元素上
2.在JavaScript中分析拖放的文件
3.在客户端加载和解析该文件
4.使用XMLHttpRequest2异步上传该文件
5.以图形的方式显示上传进度条
6.使用渐进增强(Progressive Enhancement)的思维来保证文件上传操作可以在任何浏览器上进行(对IE6的粉丝来说这是个好消息)
7.使用简单的JavaScript编码,不需要任何库
关于浏览器支持
开始之前,说明一下,因为本教程引用了许多最新的HTML5技术,所以可能支持度不同。下面的代码现在可以运行,但可能未来APIs接口有变或浏览器升级会造成影响。
最近发布的Firefox和Chrome版本支持所有的特性并能完美运行
Opera可以在JavaScript中解析文件,但是通过拖放文件并用XMLHttpRequest2进行上传现在还没实现
IE和桌面版的Safari不支持本文设计的任何APIs
Apple关闭了iPhone和iPad上Safari的通过HTML上传文件的表单。有人知道为什么吗?
最后,注意理解我这些代码中的基本概念,如果要在产品中使用还需要做仔细的检查。
HTML和CSS
在这里,我们写了一个标准的文件类型的输入表单,唯一属于HTML5特性的属性是“multiple”,它可以允许用户选择多个文件。
我们将把文件上传到用PHP编写的服务端,当然你也可以选择其他任何技术来实现服务端,但这里的代码都基本相同。MAX_FILE_SIZE这个隐藏属性的值设置为300,000个字节,是PHP中用来在客户端防止用户上传过大的文件。
ID为filedrag的层用来作为文件拖放的目标位置,在CSS中默认将其隐藏,但如果当前浏览器支持拖放功能时,则在使用JavaScript将其显示。
我们还需要定义一个 .hover类,用在当用户把文件拖上来时改变层的样式。在这种状态下浏览器不会自动加上a :hover这个类,但是当事件产生时,我们可以通过JavaScript来完成。
文件API
W3C File API 提供了许多对象,我们将用到:
FileList: 表示所选文件的列表
File: 表示单个文件
FileReader:允许使用JavaScript来读取和使用文件的接口
编写JavaScript事件
是时候开始编写JavaScript了。因为我们没有使用JavaScript的类库,所以为了方便,我们有必要编写两个辅助的方法:通过ID寻找元素和输出信息。
现在我们需要确定File API可用并且调用Init()方法。
Init()方法:
1.为文件输入表单增加一个名为“change”的事件监听器
2.将ID为filedrag的层设为可见
3.为ID为filedrag的层增加样式变化事件监听器“dragover”和“dragleave”
4.为ID为filedrag的层增加名为“drop”的事件监听器
5.隐藏提交按钮——在对所选文件进行解析和上传时它是不必要的
当然,如果浏览器支持拖放文件,你也可以隐藏文件输入表单。我个人而言,更喜欢两种方式都使用,这样可以避免因为拖放所带来的一些可用性问题。对XMLHttpRequest.upload的检查是为了避免在Opera中出现问题。Opera支持FileList、File和FileReader接口,但不支持拖放事件和XMLHttpRequest2。因此,Opera能显示文件信息,但却不能做到显示ID为filedrag的层和隐藏提交按钮。
文件拖放后的样式变化
很少人有在浏览器中拖放文件的经历。实际上,有经验的web用户也不太关心文件拖放是否可能。因此,我们用一个层来提醒用户“把文件拖放到这里”(“drop files here”),更进一步,当一个文件已经拖放到指定位置后,我们还需要通过改变ID为filedrag的层的样式来进行提醒。
分析拖放或选择后的文件
我们用同一个方法FileSelectHandler()来处理一个或多个文件,而不用关心文件是通过文件输入表单的“Browse”来选择,还是直接把文件拖放到ID为filedrag的层上。
方法说明:
1.调用FileDragHover()方法来移除悬停(hover)样式和取消浏览器事件。这是必不可少的,否则浏览器会尝试显示这个文件。
2.获取一个FileList对象。这个对象不是从文件输入表单获取(如:e.target.files)就是从ID为filedrag的层上(如:e.dataTransfer.files)。
3.最后,遍历FileList并将每一个File对象作为ParseFile()的参数进行调用
上面这个方法用来输出文件信息,用的是File对象中的三个主要的只读属性:
.name: 文件名(不包括路径)
.type: 文件MIME类型, 如: image/jpeg, text/plain, 等等
.size: 文件大小,单位字节
这是实例页面,你需要用Firefox, Chrome, 或Opera (不支持拖放)来访问,你也可以点击这里下载代码实例。