前端必知必会之文件上传攻略(一)
程序员文章站
2022-08-19 17:54:20
文件上传原理 根据http协议的定义,完成请求消息体的封装和解析,将二进制内容保存至文件。 关键字: multipart/form-data 含义: multipart表示资源有多种元素组成,form-data使用post方式或HTML Forms上传文件。 结构: 请求头:表示本次请求要上传文件, ......
文件上传原理
根据http协议的定义,完成请求消息体的封装和解析,将二进制内容保存至文件。
关键字:
multipart/form-data
含义:
multipart表示资源有多种元素组成,form-data使用post方式或html forms上传文件。
结构:
- 请求头:表示本次请求要上传文件,其中boundary表示分隔符。
content-type: multipart/form-data; boundary=----webkitformboundary2ahjiirvmka4qn78
- 消息体- form data 部分
content-disposition: form-data
为固定值,表示一个表单元素,name
表示表单元素的 名称,回车换行后面就是name
的值,如果是上传文件就是文件的二进制内容。
content-type
:表示当前的内容的 mime 类型(type/subtype)通用+子类,是图片还是文本还是二进制数据(text/.. application/... image/... video/...)。
解析:
客户端发送请求到服务器后,服务器拿到请求的消息体进行解析,解析出哪些是普通表单哪些是附件。一般不需要自行解析,有第三方库可用。
无刷新上传
关键字:
xmlhttprequest
xmlhttprequest2有了升级,首先就是可以读取和上传二进制数据,可以使用·formdata·对象管理表单数据。
示例:
<div> 选择文件(可多选): <input type="file" id="f1" multiple/><br/><br/> <button type="button" id="btn-submit">上 传</button> </div>
<script> function submitupload() { //获得文件列表,注意这里不是数组,而是对象 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',submitupload); </script>
实现进度条
借助xmlhttprequest2,实现单文件或多文件的上传进度条。
说明
- 页面内增加一个用于显示进度的标签
div.progress
-
js
内处理增加进度处理的监听函数xhr.upload.onprogress
-
event.lengthcomputable
这是一个状态,表示发送的长度有了变化,可计算 -
event.loaded
表示发送了多少字节 -
event.total
表示文件总大小 - 根据
event.loaded
和event.total
计算进度,渲染div.progress
<div> 选择文件(可多选): <input type="file" id="f1" multiple/><br/><br/> <div id="progress"> <span class="red"></span> </div> <button type="button" id="btn-submit">上 传</button> </div>
<script> function submitupload() { var progressspan = document.getelementbyid('progress').firstelementchild; var filelist = document.getelementbyid('f1').files; progressspan.style.width='0'; progressspan.classlist.remove('green'); if(!filelist.length){ alert('请选择文件'); return; } var fd = new formdata(); //构造formdata对象 fd.append('title', document.getelementbyid('title').value); for(var i =0;i<filelist.length;i++){ fd.append('f1', filelist[i]);//支持多文件上传 } var xhr = new xmlhttprequest(); //创建对象 xhr.open('post', 'http://10.70.65.235:8100/', true); xhr.onreadystatechange = function () { console.log('state change', xhr.readystate); if (xhr.readystate == 4) { var obj = json.parse(xhr.responsetext); //返回值 console.log(obj); if(obj.fileurl.length){ //alert('上传成功'); } } } xhr.onprogress=updateprogress; xhr.upload.onprogress = updateprogress; function updateprogress(event) { console.log(event); if (event.lengthcomputable) { var completedpercent = (event.loaded / event.total * 100).tofixed(2); progressspan.style.width= completedpercent+'%'; progressspan.innerhtml=completedpercent+'%'; if(completedpercent>90){//进度条变色 progressspan.classlist.add('green'); } console.log('已上传',completedpercent); } } //注意 send 一定要写在最下面,否则 onprogress 只会执行最后一次 也就是100%的时候 xhr.send(fd);//发送时 content-type默认就是: multipart/form-data; } //绑定提交事件 document.getelementbyid('btn-submit').addeventlistener('click',submitupload); </script>
ps 特别提醒
xhr.upload.onprogress
要写在xhr.send
方法前面,否则event.lengthcomputable
状态不会改变,只有在最后一次才能获得,也就是100%
的时候.
上一篇: 真送分题