JS34 文件上传前实时预览
上传图片前在本地预览的方法。
概述
上传图片前在本地预览
当使用<input type="file">
上传图片文件时,如何在上传到服务器之前,在本地进行预览?
FileReader
对象
FileReader
对象允许Web应用程序异步读取用户计算机上的文件。使用new
创建一个FileReader
实例对象:
1 | const fileReader = new FileReader(); |
属性
error
:在读取时发生的错误readyState
:fileReader
当前状态result
:读取到的文件内容,只有在读取操作完成后有效
方法
abort()
:终止读取操作readAsDateURL()
:读取文件中的内容,读取完成后调用onloadend
方法,结果result
中包含一个data:URL
格式的字符串表示文件内容(针对图片就是base64
格式的字符串)
事件处理程序
onabort
:读取被终止时被调用onerror
:读取错误时调用onload
:读取成功时调用onloadend
:读取完成时调用,无论成功失败, 在onload
或onerror
后调用onloadstart
:读取开始前调用onprogress
:读取过程中周期调用、
兼容性
可以看出除了IE系列支持不太好之外,包括Edge在内兼容性还是不错的。
使用FileReader
对象预览图片
- 在
<input>
的onchange
事件中获取上传的图片对象 - 使用
<input>
的event.target.files
获取上传对象的类数组对象,每一项的name
属性对应文件名 <input>
中增加multiple
属性,上传多个文件- 创建
FileReader
对象,并通过readAsDateURL()
方法,传入要预览的文件对象,在onload
回调函数中对FileReader
对象的result
进行处理
预览多张图片的Demo:
1 | <body> |
由于FileReader
读取的过程是一个异步函数,我们可以封装为一个Promise形式进行更方便的调用:
1 | function asyncPreview(file) { |
拖拽预览
不通过点击事件而是通过将图片拖拽到指定区域实现预览。
在拖放过程中会触发的事件:
- 在源元素上触发的事件(需要设置
draggable
属性)ondragstart
:开始拖动时触发ondrag
:拖动时触发ondragend
:拖动完成时触发
- 释放时触发的事件
ondragenter
:进入容器范围时触发ondragover
:拖动时触发(触发间隔350毫秒)ondragleave
:离开容器范围时触发ondrop
:拖动过程中,释放鼠标按键时触发
显然这里需要使用的是ondrop
事件,但是需要注意,使用ondrop
事件需要阻止浏览器dragenter
、dragleave
、dragover
和drop
事件的默认行为,否则不会触发
1 | // 释放 |
在ondrop
事件中触发上面的函数preview
就可以实现图片预览了。注意,input
的onchange
事件获取文件对象是e.target.files
,而drop
事件则是e.dataTransfer.files
如果报错event.js:501 Uncaught TypeError: this._drop is not a function
是因为事件冒泡的原因,所以要增加e.stopPropagation()
window.URL.createObjectURL()
也可以通过这个方法来实现图片的预览
它对IE的支持比fileReader
稍好一些
window.URL
属性返回一个对象,它提供了用于创建和管理对象URLs的静态方法。它也可以作为一个构造函数被调用来构造URL对象。
URL.createObjectURL()
静态方法会创建一个 DOMString
,这个新的URL 对象表示指定的File
对象或Blob
对象。
在每次调用createObjectURL()
方法时,都会创建一个新的URL
对象,即使已经用相同的对象作为参数创建过。当不再需要这些URL
对象时,每个对象必须通过调用URL.revokeObjectURL()
方法来释放。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。
1 | // 使用 createObjectURL |
fileReader
和URL.createObjectURL
的区别
(1)兼容性
URL.createObjectURL()
对IE10和IE11的支持更好一些,但是总体上来说,二者兼容性是差多不的
(2)异步
fileReader
是异步读取的过程,而URL.createObjectURL()
是同步读取的,所以如果是读取比较大的图片会对性能有一定影响。为了解决这个问题可以再Web Woker中完成读取的操作。
(3)释放
上面提到了,使用URL.createObjectURL()
时,从性能角度出发,可以通过手动调用URL.revokeObjectURL()
来释放URL
对象