文件上传总结
文件上传的方式有哪些(Flash已经淘汰,不再提及)
目前常用的只有2种
1. form上传
就是使用 inputFile 控件,form的enctype必须是 multipart/form-data
<form method="post" action="http://uploadUrl" enctype="multipart/form-data"> <input name="file" type="file" accept="image/gif,image.jpg" /> <input name="token" type="hidden" /> <input type="submit" value="提交" /> </form>
1.1 多文件上传
inputFile 支持多文件上传, multipart属性 <input type="file" multipart />
1.2 无刷新上传
iframe + form 可以实现无刷新上传,将form的target设置为一个隐藏的iframe。
1.3 提交额外数据
form中可以使用input hidden提交隐藏字段,比如token等。
1.4 inputFile的美化
1.4.1 用透明度为0的 input file 覆盖美观的按钮
1.4.2 用label标签的for指向inputFile控件,美化label标签
2. ajax上传
使用的是XMLHttpRequest level2 + FormData, 或者是 Fetch + FormData
<form> <input type="file" id="f1" multiple/><br/><br/> <button type="button" id="btn-submit">上 传</button> </form>
//XMLHttpRequest function uploadFiles() { //获得文件列表,注意这里不是数组,而是对象 var fileList = document.getElementById('f1').files; if(!fileList.length){ alert('请选择文件'); return; } var fd = new FormData(); //构造FormData对象 fd.append('title', document.getElementById('title').value); //多文件上传需要遍历添加到 fromdata 对象 for(var i =0;i<fileList.length;i++){ fd.append('f1', fileList[i]);//支持多文件上传 } var xhr = new XMLHttpRequest(); //创建对象 xhr.open('POST', 'http://localhost:8100/', true); xhr.send(fd);//发送时 Content-Type默认就是: multipart/form-data; xhr.onreadystatechange = function () { console.log('state change', xhr.readyState); if (this.readyState == 4 && this.status == 200) { var obj = JSON.parse(xhr.responseText); //返回值 console.log(obj); if(obj.fileUrl.length){ alert('上传成功'); } } } } //绑定提交事件 document.getElementById('btn-submit').addEventListener('click',uploadFiles);
//Fetch fetch('http://uploadUrl', { method: 'POST', body: fd }) .then(response => response.json()) .then(response =>{ console.log(response); if (response.fileUrl.length) { alert('上传成功'); } } ) .catch(error => console.error('Error:', error));
2. 文件上传体验优化
2.1 上传进度
使用 xhr.onprogress 和 xhr.upload.onprogress
2.2 文件预览,主要是图片
img.src = window.URL.createObjectURL(file) //createObjectURL得到文件对象的blob url, 赋值给img的src即可
2.3 文件终止上传
xhr.abort()
2.4 文件拖曳上传
监听拖曳区域的drag释放事件,dragover,dragleave,drop事件,在drop事件中获取file对象,在通过ajax上传。
2.5 剪贴板上传
监听输入区域的paste事件,获取剪贴板数据,提取file数据,ajax上传成功后,将返回的图片地址赋值到一个image对象上,插入到光标处。
通常该输入区域,是一个 contentEditable 的 div,而不是textarea,因为其无法承载其他html元素
2.6 大文件上传
2.6.1 分片
大文件分片上传,分片传完后,再发送一个合并请求,告诉服务端上传文本,合并文件。服务端根据文件标识,合并文件。
文件标识,可以使用 文件名 和 序号。
文件分片的基本方法是,blob对象slice方法,blob.prototype.slice,File对象继承了Blob,文件也可以进行slice。
2.6.2 断点续传
对分片生成hash,将hash保存在服务端,下次上传从服务端获取hash信息,对比本地分片的hash,已经上传的部分进行
秒传,即只显示上传进度完成,跳过上传,只上传未上传的分片。
参考:https://juejin.im/post/5da14778f265da5bb628e590
https://www.cnblogs.com/sunliyuan/p/5737928.html