HTML5中使用type=file的input上传文件权威指南
一 、入门
下面是大家非常熟悉的html5的文件上传代码,可不保证每个人都真的理解背后的知识点。
<input type="file" id="input">
当我们点击file标签的时候一定会弹出文件选择的界面,当我们选择一个图片或者文件时,浏览器dom中会产生一个fileList对象。
通过DOM API我们可以访问到这个file对象的数组列表。
二 FileList中的file对象
File 对象提供了三个属性,包含了文件的有用信息。
- name 文件名称,只读字符串。只包含文件名,不包含任何路径信息。
- size 文件大小,按字节数(bytes)计算,只读的64位整数。
- type 文件的MIME类型,只读字符串,当类型不能确定时为""。
通过dom api获取fileList
const selectedFile = document.getElementById('input').files[0];
选择1个文件的时候,可以获取数组的第一个元素。
通过onchange事件访问fileList
<input type="file" id="input" multiple onchange="handleFiles(this.files)">
注:如果你想让用户选择多个文件,只需在input元素上使用multiple属性。
动态监听change事件获取fileList(推荐,常用)
const inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
}
三 input的click事件(和change事件区别)
上面提到了change事件,触发的场景就是fileList对象内容的改变。这种改变是弹出文件选择框,并选择了文件改变后才触发。而触发弹出文件选择框的事件是click事件。掌握这一点,可以帮我们优雅的解决业务问题。
使用图片代替原本丑陋的input按钮
方式1:使用一个image标签和input绝对定位,保持两者大小一致重叠。这样点击图片时,就可以触发input的弹出选择文件窗口。这种方式网上很流行,其实是初学者无奈之举,不好控制。
方式2: 推荐
# H5中隐藏按钮,无需做其他事情
<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<button id="fileSelect">Select some files</button>
# 顶一个可见的button,点击button的时候触发input的click事件
const fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem");
fileSelect.addEventListener("click", function (e) {
if (fileElem) {
fileElem.click();
}
}, false);
四,如何展示图片
只有两种方式,图片的url或者base64,具体可以参考我的另外一篇博客。
通过图片的URL显示缩略图(重要)
function handleFiles(files) {
# 获取每一个图片对象
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /^image\//;
if (!imageType.test(file.type)) {
continue;
}
# 在dom上创建一个image标签,并且挂载到priview的div内部。
var img = document.createElement("img");
img.file = file;
preview.appendChild(img); // 假设"preview"就是用来显示内容的div
# 重点,读取图片的file(blog)对象,并且将返回的url设定到img的src属性中
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
最后一步再解释一下,FileReader是一个异步读取图片的函数,和读普通文件没区别,读取结束后会触发onload事件。
reader.readAsDataURL(file);开始执行,onload后面其实是后面才执行。
五 如何上传图片
假设已经获取到了图片的file对象,这是可以通过多种方式上传给后端。这里展示的ajax的方式。还有很多其他方法,我们需要理解一点
注:如果后端想获取到文件,并转存上传的需要是file对象。而不是url,url很可能本地的,上传给后端是无法读取的。
<script type="text/javascript">
function FileUpload(blog) {
var formdata = new FormData($("#contact-form")[0]);
formdata.append("brokerId", brokerId);
formdata.append("age", age);
if (blog != "") {
formdata.set("file", blog, blog.name);
}
$.ajax({
type: "POST",
url: prefix + "customers/add",
data: formdata,
processData: false,
contentType: false,
dataType: "json",
success: function(data) {
if (data.code == 0) {
console.log("添加成功" + data.code);
$(window).attr('location', 'mycustomers.html');
} else {
alert("添加客户遇到错误!")
}
},
error: function(data) {
alert("添加客户遇到网络错误!")
console.log(data);
}
});
}
</script>
待续
还有几点,今天没时间,可以顺带提一下。
url是一个字符串,但是可以通过字符串找到图片的位置,url必须指向一个对象。
base64其实是文件对象的另外一种存储形式,这种形式可以用来在网络中传播。img的src也可以读取base64格式的数据,直接显示为图像。
如果你src指向的是base64,无论是否联网你都能显示图片,因为base64就代表了图片本身。
参考:
文章来源于此,很多内容没有介绍,个人也做了补充
https://developer.mozilla.org/zh-CN/docs/Web/API/File/Using_files_from_web_applications