JavaScript 拖拽文件上传和本地图片预览
在图形界面的操作系统中,拖拽操作应该是一个比较常见的功能。比如 对于不太懂电脑的小白来说最简单的删除文件的方式就是把文件拖到桌面上的回收站图标,打开文件也是直接拖到相应的软件中。拖拽操作可以说是最便于小白理解的一种操作方式。
拖拽文件上传
目前大多数的网络相册和网盘都支持直接拖拽文件上传,例如,百度网盘、Google 云端硬盘、Google 相册 等,都支持拖拽文件上传。不过要使用拖拽文件上传浏览器必须要能很好的支持 HTML5,也就是说那些老 IE 都是用不了的。
这里先放一个 div
来接收文件:
<div>把文件拖到此处上传</div>
给 div
加一些 CSS 方便查看:
div{
width: 300px;
height: 300px;
background: #00e080;
color: #ffffff;
font-size: 20px;
text-align: center;
line-height: 300px;
}
效果如下:
我这里只是为了方便演示,在实际的开发中接收文件的范围可以大一些,下面是 JS:
var Div = document.querySelector('div'); // 获取div
// 文件进入div
Div.ondragenter = function(event) {
// 阻止浏览器默认事件
event.preventDefault();
event.stopPropagation();
};
// 文件在div上,但是还未松开鼠标
Div.ondragover = function(event) {
// 阻止浏览器默认事件
event.preventDefault();
event.stopPropagation();
};
// 文件进入Div并且已经松开鼠标
Div.ondrop = function(event) {
// 阻止浏览器默认事件
event.preventDefault();
event.stopPropagation();
// 把文件传入files变量,有的浏览器需要通过event获取
var files = this.files || event.dataTransfer.files;
// 新建FormData对象
var formData = new FormData();
// 封装一个formData
formData.append('files', files[0]);
// 新建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 设置提交方式 url 是否异步
xhr.open('post', 'server.php', true);
// 设置请求头
xhr.setRequestHeader('X-Request-With', 'XMLHttpRequest');
// 提交数据,传入已封装的FormData
xhr.send(formData);
// 此方法在成功提交并接收到数据的时候触发
xhr.onreadystatechange = function () {
// 验证一下是否全部接收完成
if (xhr.readyState == 4) {
// 在控制台输出接收到的数据
console.log(xhr.responseText);
}
}
};
这里因为有注释和空行,所以看起来内容很多,实际上很简单,下面是详细说明:
dragenter 事件
被拖动的内容进入目标元素时触发,上面的文件如果拖入到div就会触发,在不放开鼠标的情况下也会触发,event.preventDefault()
主要是禁止浏览器的默认事件,有的浏览器文件拖入以后可能会直接读取文件,详细的 preventDefault
说明可以访问: https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault 。event.stopPropagation()
主要是阻止冒泡,详细的可以看: https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopPropagation 。
dragover 事件
被拖动的内容在目标元素上时触发,而且是连续触发,上面 的文件拖入 div
内只要不离开就会连续触发。
drop 事件
被拖动的内容进入目标元素并且已经放开鼠标时触发,上面的文件进入 div
放开鼠标后触发,如果文件移出 div
放开鼠标也不会触发。
this.files 属性
获取拖入的文件列表,一般用于input
这一类的元素。
event.dataTransfer.files 属性
获取拖入的文件列表,一般用于div
这一类和文件无关的元素。
event.originalEvent.dataTransfer.files 属性
一般用于j Query 获取文件列表,这里没有用到。
上面的两种方式都是获取拖入的文件列表,文件拖入后会返回一个包含文件列表的数组,数组的长度取决于文件数量。我上面上传的是第一个文件。文件列表中的文件又包含一些属性,下面是详细说明:
属性 | 类型 | 读/写 | 说明 |
---|---|---|---|
lastModified | Number | 只读 | 文件最后修改时间,1970年1月1日到现在的时间戳。 |
lastModifiedDate | object | 只读 | 文件的最后修改日期。 |
name | string | 只读 | 文件名,不包含路径。 |
type | string | 只读 | 文件类型,如 image/png 。 |
size | Number | 只读 | 文件大小(字节)。 |
以上面的 files 数组为例,我想获取第一个文件的大小,代码如下:
files[0].size
到这里拖拽的部分就算是写完了,关于 FormData
和 XMLHttpRequest
可以看下面两篇文章:
这里获取的 files
文件对象和文件表单的 files
对象是一样的。
预览本地图片
在用户上传头像或各种图片背景时可以在正式上传之前就加载图片让用户预览,满意在上传,避免用户多次更换头像造成服务器带宽和空间的浪费。
这里用的是文件表单选择文件,用拖拽的方式也可以实现,主要还是需要 files
对象,下面是 HTML:
<input type="file">
<img src="" alt="图片">
设置一下 img
的宽度和高度,方便演示:
img{
width: 640px;
height: 360px;
background: #f0f0f0;
border: 1px solid #0063b1;
display: block;
}
效果如下:
在实际开发中可以隐藏文件表单,用按钮调用文件表单来选择文件。
下面是 JS 代码:
var Img = document.querySelector('img'); // 获取img
var fileInput = document.querySelector('input'); // 获取文件表单
// 文件表单的内容改变,也就是选择完文件触发
fileInput.onchange = function() {
// 如果未选择任何文件
if (fileInput.value == '') {
return false;
}
// 创建FileReader对象
var reader = new FileReader();
// 读取文件
reader.readAsDataURL(fileInput.files[0]);
// 读取文件完成时触发
reader.onload = function (event) {
// 设置img的src
Img.src = event.target.result;
};
};
最终效果如下:
下面是详细说明:
change 事件
在域的内容改变时触发,例如 input
的内容改变就会触发,选择完文件后文件表单的 value
会变为选择的文件的文件名,如果选择了多个文件也只会显示第一个文件的文件名。
FileReader 对象
FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。
readAsDataURL() 方法
readAsDataURL
方法会读取指定的 Blob
或 File
对象。读取操作完成的时候,readyState
会变成已完成 DONE,并触发 loadend
事件,同时 result
属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
FileReader.onload 事件
FileReader
的 onload
事件会在文件读取完成时触发。
下面是 FileReader
的一些事件说明:
事件 | 说明 |
---|---|
FileReader.onabort | 处理abort事件。该事件在读取操作被中断时触发。 |
FileReader.onerror | 处理error事件。该事件在读取操作发生错误时触发。 |
FileReader.onload | 处理load事件。该事件在读取操作完成时触发。 |
FileReader.onloadstart | 处理loadstart事件。该事件在读取操作开始时触发。 |
FileReader.onloadend | 处理loadend事件。该事件在读取操作结束时(要么成功,要么失败)触发。 |
FileReader.onprogress | 处理progress事件。该事件在读取Blob时触发。 |
event.target.result 属性
在 readAsDataURL
读取文件完成后会返回一个URL,把 img
的 src
设置为 readAsDataURL
返回的图片URL就能显示图片了。
以上就是 JavaScript 拖拽文件上传和预览本地图片的方法,无论是拖拽上传还是预览本地图片都需要浏览器支持 HTML5。
相关参考文章:
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/594/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。