ajax异步上传文件带进度条

前言

虽然很多前端框架已经实现异步上传文件带进度条的,而且都特别美观开箱即用,但有时候就是想自己实现一下;本文用到 FormData 对象实现异步上传,用 xhr对象的 upload 属性监听上传进度。
注意:
这个进度只是客户端上传进度,并非实际服务器端收到的进度

技术支持

  1. file 类型的 input 对象有一个 files 属性,里面存的文件列表,它的属性信息如下
    ajax异步上传文件带进度条_第1张图片
  2. files 是一个 array 说明一个 file 对象是可以上传多个文件的,设置方式如下
<input type="file" name="files" multiple />
  1. FormData 是一个表单域对象 ,可以拼接多个键值对,支持 blob 数据类型
  2. 通过 $.ajaxSettings.xhr()获取 xhr 对象
  3. 可以通过 xhr.upload.addEventListener("progress",progressFunction, false); 设置监听进度函数,progressFunction 函数的参数是 event 对象

上代码

代码可能有点乱,样式,脚本和 html 全在一个文件中,但为了演示足够,一般也不会自己写,而是用框架。


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传title>
head>
<body>
    <fieldset>
        <legend>单文件上传legend>
        <div >
            <input type="file" name="file" />
        div>
        <div ><button class="">上传button>div>
        <div><label for="">进度:<b>b>label><progress value="0" max="100" >progress>div>
    fieldset>

    <fieldset>
        <legend>多文件上传legend>
        <div >
            <input type="file" name="file" multiple />
        div>
        <div ><button class="">上传button>div>
        <div><label for="">进度:<b>b>label><progress value="0" max="100" >progress>div>
    fieldset>

<script src="jquery-1.8.3.min.js">script>
<script>
$(function () {
    $('input[type=file]').bind('change',function () {
        var $fieldset = $(this).closest('fieldset');
        var files = this.files;
        var totalLength = 0;
        for(var i=0;i<files.length;i++){
            totalLength += files[i].size;
        }
        var $process = $fieldset.find('progress');
        $process.attr('max',totalLength);
    });

    $('button').bind('click',function () {
        var $fieldset = $(this).closest('fieldset') ;
        var $files = $fieldset.find('input[type=file]');
        var $process = $fieldset.find('progress');

        var formData = new FormData();
        var totalFileSize = 0;
        for (var i = 0; i < $files.size(); i++) {
            var domfile = $files[i];
            var nameKey = $files.eq(i).attr('name');

            for (var j=0;j<domfile.files.length;j++) {
                formData.append(nameKey,domfile.files[j]);
                totalFileSize++;
            }
        }


        ajaxUpload(formData,$fieldset,totalFileSize);

    });
    
    function progressFunction(event) {
        // console.log(event)
        var $currentFieldset = arguments.callee.current;
        $currentFieldset.find('progress').attr('value',event.loaded);
    }

    function ajaxUpload(formData,$fieldset,totalFileSize) {
        $.ajax({
            url: totalFileSize == 1 ?  '/upload/single':'/upload/multi',
            cache: false,
            type: "POST",
            data: formData,
            dateType:'json',
            processData:false,
            contentType:false,
            xhr: function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
               var  myXhr = $.ajaxSettings.xhr();
                if( myXhr.upload) {
                    //绑定progress事件的回调函数
                    progressFunction.current = $fieldset;
                    myXhr.upload.addEventListener("progress",progressFunction, false);
                }
                return myXhr; //xhr对象返回给jQuery使用
            },
            error: function(request) {
                alert("Connection error");
            },
            success: function(data) {
                console.log(data)
            }
        });
    }
});
script>
body>
html>

完整代码

github:https://gitee.com/sanri/example/tree/master/test-mvc

sanri-tools 工具

创作不易,希望可以推广下我的小工具,很实用的解决项目中的一些麻烦的事情,欢迎来 github 点星,fork
github 地址:https://gitee.com/sanri/sanri-tools-maven
博客地址:https://blog.csdn.net/sanri1993/article/details/98664034

你可能感兴趣的:(前端)