在前端开发中,拖拽上传文件是一种很常见的需求。经过拖拽来实现文件上传须要了解FileReader
这个File API
以及对应的拖拽事件前端
咱们先了解一下,在前端表单中是如何处理文件上传的浏览器
一直以来,咱们都经过<input type='file'>
字段来获取文件的对应信息。HTML5为文件输入元素添加了一个files
集合,在files
集合中,有一组File
对象,每一个File
对象对应着一个文件bash
File
对象属性(只读属性):服务器
属性 | 类型 | 描述 |
---|---|---|
name | 字符串 | 本地文件系统中的文件名 |
size | 数字 | 文件的字节大小 |
type | 字符串 | 文件的MIME类型 |
lastModifiedDate | 字符串 | 文件上一次被修改的时间 |
具体的实现代码以下:app
<input type='file' id='files'>
<script>
var files = document.getElementById('files')
files.addEventListener('change', function(event) {
console.log(event.target.files)
console.log(
`文件名称:${event.target.files[0].name}
文件类型:${event.target.files[0].type}
文件大小:${event.target.files[0].size} bytes`
)
})
</script>
复制代码
实例结果截图:异步
靠files
集合只能知道一些文件的基本信息,FileReader
类型才是File API
的重头戏post
FileReader
类型实现是一种异步文件读取机制,读取的是文件系统。能够经过如下方法读取文件中的内容ui
方法名 | 参数 | 输出内容 | 描述 |
---|---|---|---|
readAsText | file,encoding | 纯文本 | 异步以纯文本形式读取文件,将读取到的文本保存在result属性中 |
readAsDataURL | file | DataURI的形式 | 异步读取文件并将文本以数据URI的形式保存在result属性中 |
readAsBinaryString | file | 二进制 | 异步读取文件内容并将包含文件内容的二进制字符串保存在result属性中 |
readAsArrayBuffer | file | ArrayBuffer | 异步读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中 |
abort | -- | -- | 用于中断文件读取过程 |
具体文件输出代码:url
<input type='file' id='files'>
<script>
var files = document.getElementById('files')
files.addEventListener('change', function (event) {
let file = event.target.files[0]
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function () {
console.log(reader.result)
}
})
</script>
复制代码
咱们以上传图片,输出DataURL
为例spa
其余三种不一样的文件输出,只需将上述reader.readAsDataURL(file)
的代码替换方法便可,因为篇幅有限,就不在此展开,读者能够建立对应的文件一一尝试
由于文件读取过程是异步的,FileReader
也提供了几个对应的事件,同时在上述的代码中,咱们也已经使用了FileReader
中的load
事件来判断是否已经读完整个文件
事件名称 | 事件描述 |
---|---|
onabort | 读取被终止时调用 |
onerror | 读取出错时调用 |
onload | 读取成功时调用 |
onloadend | 读取完成时调用,无论是读取成功仍是失败 |
onloadstart | 读取将要开始时出发 |
onprogress | 读取过程当中周期性触发,每50ms左右触发一次,能够用来监听文件读取的进度 |
有时候,咱们只想读取文件的一部分而不是所有内容。为此,File
对象还支持了一个slice()
方法,slice()
方法接受两个参数:起始字节数以及要读取的字节数。这个方法返回一个Blob
实例,Blob是File类型的父类型
咱们新建一个从1到10的txt
,读取1-5的内容
输出结果:
如下就是读取文件部份内容的代码
<input type='file' id='files'>
<script>
var files = document.getElementById('files')
files.addEventListener('change', function (event) {
let file = event.target.files[0]
let reader = new FileReader()
blob = file.slice(0, 10)
reader.readAsText(blob)
reader.onload = function () {
console.log(reader.result)
}
})
</script>
复制代码
有时候咱们想要上传图片以后,直接在网页中展现出来,这时候,咱们就可使用对象URL
。
对象URL
也被称为blob URL
,指的是引用保存在File
或Blob
中数据的URL
,要建立对象URL
,可使用window.URL.createObjcetURL()
方法,并传入File
或Blob
对象,方法就会返回一个字符串,指向一块内存地址。那么咱们就能够动态将字符串URL
插入img
标签中,从而实现网页上传图片展现了
具体代码以下:
<input type='file' id='files'>
<div id='images'></div>
<script>
var files = document.getElementById('files')
var images = document.getElementById('images')
files.addEventListener('change', function (event) {
let file = event.target.files[0]
url = window.URL.createObjectURL(file)
if (url) {
images.innerHTML = `<img width='300' height='300' src=${url} />`
}
})
</script>
复制代码
若是已经不须要了相对应的对象URL
数据,最好释放它占用的内容。咱们能够经过将对象URL
传给window.URL.revokeObjectURL()
,那么就能手工释放其占用的内存
咱们能够结合HTML5拖拽API
和文件API
,来实现从桌面把文件拖放到对应网页的目标上。从桌面上把文件拖放到浏览器中会触发drop
事件,从而就能经过event.dataTransfer.files
读取到拖拽文件的信息
当文件拖拽网页位置上以后能获取到文件的信息:
具体代码以下:
<div id='droptarget' style="width: 200px; height: 200px; border:1px solid black"></div>
<script>
var droptarget = document.getElementById('droptarget')
droptarget.addEventListener('drop', function (event) {
event.preventDefault(); //禁止浏览器默认行为,浏览器默认会直接打开显示
if (event.type === 'drop') {
//获取文件信息,同File对象相同
var files = event.dataTransfer.files;
console.log(
`文件名称:${files[0].name},文件类型:${files[0].type},文件大小:${files[0].size} bytes`
)
}
})
droptarget.addEventListener('dragenter', function (event) {
//禁止浏览器默认行为,浏览器默认会直接打开显示
event.preventDefault();
})
droptarget.addEventListener('dragover', function (event) {
//禁止浏览器默认行为,浏览器默认会直接打开显示
event.preventDefault();
})
</script>
复制代码
咱们已经能够经过File API
来访问到文件中的内容,那么咱们就能够利用这一点来经过XHR
实现文件的上传。咱们能够经过FormData
以表单的方式来上传文件内容。首先咱们建立一个FormData
对象,经过调用append()
方法并传入相应的File
对象做为参数,再经过XHR
的send()
方法,就能够将文件内容上传到服务器端。
具体的代码根据上面的读取拖拽文件代码进行改造,从而实现拖拽文件上传:
droptarget.addEventListener('drop', function (event) {
event.preventDefault();
if (event.type === 'drop') {
var data = new FormData();
var files = event.dataTransfer.files;
data.append("file", files[0]) //若是有多个文件上传,可对应遍历files对象加入到data中
var xhr = new XMLHttpRequest();
xhr.open('post', url, true); //url表示文件上传服务器的地址
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
console.log(xhr.responseText)
}
}
}
xhr.send(data);
})
复制代码
若是以为文章对你有帮助,请帮忙多多点赞,动动小手,你的点赞是我写做最大的动力