欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

前端必知必会之文件上传攻略(一)

程序员文章站 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.loadedevent.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%的时候.