文件上传原理
根据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%
的时候.
原文地址:https://www.cnblogs.com/Joe-and-Joan/p/11704571.html
时间: 2024-10-11 14:01:00