1.FileReader
FileReader 实现了一种异步的读取机制。他必须先通过 FileReader() 构造函数创建出一个 fileReader 实例。该实例实现了一下几个方法和事件(部分):
readerAsDataURL(file): 读取文件并以数据 URI 形式保存在 result 属性中
load 事件:在文件加载成功后触发 lo## 标题ad 事件
error 事件:在文件加载失败后触发 error 事件
progress 事件:在读取文件的过程中触发 progress 事件,该事件可以近似(间隔性触发,不是实时响应)监听文件上传进度。该方法有三个属性:lengthComputable(进度信息是否可用), loaded(已经加载了多少), total总共有多少。
files.forEach(function(item) {
var reader = new FileReader();
reader.readAsDataURL(item);
reader.onprogress = function(e) {
if (e.lengthComputable) {
// 简单把进度信息打印到控制台吧
console.log(e.loaded / e.total + '%')
}
}
reader.onload = function(e) {
var image = new Image()
image.src = e.target.result
body.appendChild(image)
}
reader.onerror = function(e) {
console.log('there is an error!')
}
})
对象 URL
对象 URL 指的是引用保存在 File 或 Blob 中的数据 URL。使用对象 URL 的时候不用像 FIleReader 一样要先把数据读取到 JavaScript 中,他可以引用 内存中 URL 地址而使用。
创建对象 URL 方法: window.URL.createObjectURL()。兼容写法:
function creatObjectURL(file) {
if (window.URL) {
return window.URL.createObjectURL(file);
} else if (window.webkitURL) {
return window.webkitURL.createObjectURL(file);
} else {
return null
}
}
files.forEach(function(item) {
var url = createObjectURL(item)
var image = new Image()
image.src = url
body.appendChild(image)
})
区别
-
FileReader 是异步操作,而对象 URL 是同步操作
-
FileReader.readAsDataURL 返回的是一个包含更多字节的 base64 格式,createObejctURL 返回的是一个带 hash 的 URL。
-
由于两者返回形式不同,FileReader.readerAsDataURL 会占用更多内存,但是当你不再使用他的时候,他会自动释放内存,而 createObjectURL 则只有当你的页面关闭或者手动调用 revokeObejctURL 的时候才能释放内存。
-
从兼容性来说: createObjectURL 和 FileReader.readerAsDataURL 都兼容 IE10+ 和现代所有主流浏览器
-
createObjectURL 相对 FileReader.readerAsDataURL,效率较高。但是如果图片较多,则最好手动清除内存,可以把 URL 当做参数直接传给 window.URL.revokeObjectURL()。兼容写法:
function revokeObjectURL(url) {
if (widnow.URL) {
return window.URL.revokeObjectURL(url)
} else {
return window.webkitURL.revokeObjectURL(url)
}
}
简单实现
// css
input{
display:none;
}
label{
// 关于label样式
}
// html
<input type='file' multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif' id='inputFile'>
<label for="inputFile">上传图片</label>
// js
var inputFile = document.getElementById('inputFile')
var body = document.body || document.getElementsByTagName('body')[0]
inputFile.addEventListener('change', changeHandler, false)
function changeHandler(e) {
var files = Array.from(e.target.files)
files.forEach(function(item) {
var image = new Image()
image.src = createObjectURL(item)
body.appendChild(image)
image.onload = function() {
revokeObjectURL(this.src)
}
})
}
function createObjectURL(file) {
if (window.URL) {
return window.URL.createObjectURL(file)
} else {
return window.webkitURL.createObjectURL(file)
}
}
function revokeObjectURL(file) {
if (window.URL) {
return window.URL.revokeObjectURL(file)
} else {
return window.webkitURL.revokeObjectURL(file)
}
}
拓展:URI与URL的区别
- URL(统一资源定位符)主要用于链接网页,网页组件或网页上的程序,借助访问方法(http,ftp,mailto等协议)来检索位置资源。相反,URI(统一资源标识符)用于定义项目的标识,此处单词标识符表示将一个资源与其他资源区分开,而不管使用的方法(URL或URN)
- URL是URI,但URI永远不能是URL
- URL指定要使用的协议类型,而URI不涉及协议规范
参考链接:https://juejin.cn/post/6903691429030133768
(ps. oschina上面也有很多好文章)