一次面试的时候,面试官问我,有没有自己写过文件上传,不依赖任何模板,框架?因此今天特地将文件上传那些事进行总结梳理一下。
本文使用的例子使用nodejs作为后台,jade模板作为前台的来实现文件上传的功能。当然你用其他后台语言也是可以的,我相信道理都是一样的。下面将提到几个小例子,分为普通文件上传,异步上传,显示上传进度,图片预览,多文件上传,拖拽上传这几部分。
[TOC]
普通文件上传
面试的时候问你文件上传怎么实现,一般人都能答出来,使用input标签,并将type设置为file,同时将form表单设置为multipart/form-data.恩没错,就是这样,代码如下:
这样,当我们提交表单的时候,就会上传该文件了。
那后台怎么处理呢?后台采用的是nodejs推荐的multer模块。
multer的具体用法
这里需要在根目录下建一个uploads文件夹。
异步上传
其实在实际中,我们应该更推荐使用XHR异步上传(我猜的)。这里就不得不说下XMLHttpRequest level2,和level1相比呢,有以下改进:
- 支持接收二进制数据,提供xhr.overrideMimeType()方法,或者通过设置responseType=’blob’
- 可以上传文件, 可以使用FormData对象管理表单.
- 提供进度提示, 可通过 xhr.upload.onprogress 事件回调方法获取传输进度.
- 依然受 同源策略 限制, 这个安全机制不会变. XHR2新提供 Access-Control-Allow-Origin 等headers, 设置为 * 时表示允许任何域名请求,从而实现跨域CORS访问
- 可以设置timeout 及 ontimeout, 方便设置超时时长和超时后续处理.
那我们到底应该如何使用呢?诺,像下面这样
提供进度条
html5提供了一个很好用的progress标签,通过设置total和value就可以显示进度了,并且level 2又恰好提供了onprogress回调函数,是不是感觉so easy呢
首先在jade中增加:
js中,
在shr.send调用之前加上下面代码,
其中事件的lengthComputable属性代表文件总大小是否可知,如果 lengthComputable 属性的值是 false,那么意味着总字节数是未知并且 total 的值为零。
图片预览
已经实现进度显示了(偷笑),那如何实现图片预览呢?幸运的是,html5新增的File API给我们提供了很大的帮助,这就是大名鼎鼎的FileReader。
h5给input type=file,类型的dom元素增加了files集合,通过文件输入选择一个或多个文件使,files将会包含一组File对象,因此我们可以采用var file = fileInput.files[0];这种模式获取我们选择的文件对象。同时FileReader还提供了
(1). reader.readAsDataURL(file)方法,将文件以数据URI的形式保存在reader对象的result中。
(2). 对象URL,使用对象URL的好处是可以不必把文件内容读取到js中,而直接引用文件内容。因此只要在需要文件内容的地方提供对象的URL即可。
下面就有两种方式实现图片预览
首先需要在jade中添加一个div用于预览图片
js代码如下:
第二种方式如下:
createObjectURL(file),返回的是一个字符串,指向一块内存的地址,直接把对象的url放在img标签中,img标签会找到相应的内存地址,直接读取数据并将图像显示在页面中。如果不再需要相应的数据,最好释放它占用的内容。胆只用有代码在引用对象URL,内存就不会释放。要手工释放内训,就可以调用window.URL.revokeObjectURL()方法。
|
|
这样图片预览便完美实现了,如果我们想要多个文件预览呢?
多文件预览
多文件预览首先需要设置input的 multiple属性
然后通过遍历fileInput.files中的文件,再依次调用previewImage(file)方法即可。
多文件上传
多文件上传通过遍历fileInput.files属性,并将file依次加入formData中即可, 在后台处理中调用upload.array()方法即可。
js代码如下:
后台稍微改变了一点点:
注意array中的参数一定要和formdata中的key值对应。
文件拖拽上传
h5中新增了文件拖拽api,当我们把拖拽元素(本例子中的图片文件)拖拽到目标区域(input type=file)上时,会依次触发以下事件:dragenter,dragover, dragleave或drop。因此,我们需要给input type=”file”绑定对应的处理事件。
参考
https://segmentfault.com/p/1210000009289556/read
http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html