真实的上传进度条及优化

效果预览

点击选择文件,选择了文件后即上传,上传完成后点击保存,保存成功后模态框自动关闭。

前端代码:

html

<div class='form-group'>
    <label class='col-sm-2 control-label'>上传图像:</label>
    <div class='col-sm-10'>
        <input type="file" class="newFile"/>
        <input type="hidden" name="newFileMsg" data-name=""/>
    </div>
</div>
<div class='form-group' style="display: none;" id="myModal_add_progressBar_Module">
    <label class='col-sm-2 control-label'>上传进度:</label>
    <div class='col-sm-10'>
        <div class="progress">
            <div class="progress-bar" id="myModal_add_progressBar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="width:0;" >
            </div>
        </div>
        <span id="percentage"></span><span id="time"></span>
    </div>
</div>

js

//图片上传
$(".newFile").on('change', function(e){
    var fileObj = e.currentTarget.files[0]; // js 获取文件对象
    var name = e.currentTarget.files[0].name;
    $(".newFile").parents("div.col-sm-10").find("input[name='newFileMsg']").attr("data-name",name);
    var url="/tbQuestion/uploadImg";

    var form = new FormData(); // FormData 对象
    form.append("file", fileObj); // 文件对象

    var xhr;
    xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
    xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
    xhr.onload = uploadComplete; //请求完成
    xhr.onerror =  uploadFailed; //请求失败

    xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
    xhr.upload.onloadstart = function(){//上传开始执行方法
        ot = new Date().getTime();   //设置上传开始时间
        oloaded = 0;//设置上传开始时,以上传的文件大小为0
    };
    xhr.send(form); //开始上传,发送form数据

    //显示进度条
    $("#myModal_add_progressBar_Module").css("display","block");
});

//上传成功响应
function uploadComplete(evt){
    //服务断接收完文件返回的结果
    //console.log(evt);
    var imgUrl = JSON.parse(evt.target.responseText);
    $(".newFile").parents("div.col-sm-10").find("input[name='newFileMsg']").val(imgUrl);
}
//上传失败
function uploadFailed(evt){
    parent.layer.msg("上传失败");
}
//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction(evt){
    // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
    if (evt.lengthComputable){
        $("#myModal_add_progressBar").css("width",Math.round(evt.loaded / evt.total * 100) + "%");
        $("#myModal_add_progressBar").html(Math.round(evt.loaded / evt.total * 100) + "%");
        $("#percentage").html("已上传"+Math.round(evt.loaded / evt.total * 100) + "%");
    }
    var nt = new Date().getTime();//获取当前时间
    var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
    ot = new Date().getTime(); //重新赋值时间,用于下次计算
    var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
    oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算
    //上传速度计算
    var speed = perload/pertime;//单位b/s
    var bspeed = speed;
    var units = 'b/s';//单位名称
    if(speed/1024>1){
        speed = speed/1024;
        units = 'k/s';
    }
    if(speed/1024>1){
        speed = speed/1024;
        units = 'M/s';
    }
    speed = speed.toFixed(1);
    //剩余时间
    var resttime = ((evt.total-evt.loaded)/bspeed).toFixed(1);
    $("#time").html(',速度:'+speed+units+',剩余时间:'+resttime+'s');
}

批量导入

压缩文件或单一文件的差异:

点击选择文件,选择了文件后,需点击保存后才上传,上传完成后模态框自动关闭。

当导入大文件交给后台处理时,文件上传完成,进度条到100%,但导入整个过程并没有结束,即模态框不会马上关闭。

前端代码

html

<div class='form-group'>
    <label class='col-sm-2 control-label'>选择文件</label>
    <div class='col-sm-10'>
        <input type="file" name="file" id="bulkImport"/>
    </div>
</div>
<div class='form-group' id="fileSizeModule" style="display: none;">
    <label class='col-sm-2 control-label'>文件大小</label>
    <div class='col-sm-10'>
        <input type="text" class="form-control" name="fileSize"/>
    </div>
</div>
<div class='form-group' style="display: none;" id="progressModule">
    <label class='col-sm-2 control-label'>上传进度</label>
    <div class='col-sm-10'>
        <div class="progress">
            <div id="progressBar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0"></div>
        </div>
    </div>
</div>

js

//用户点击批量导入 重置批量导入模态框
$("#clickBulkImport").click(function(){
    $("#fileSizeModule").css("display","none");
    $("#progressModule").css("display","none");
    $("#bulkImport").val("");
    $("#fileSizeModule").find("input[name='fileSize']").val("");
    $("#progressBar").attr("aria-valuemax","100");//kb
    $("#progressBar").attr("aria-valuenow","0");
    $("#progressBar").css("width","0");
});

//用户选择了上传文件
$("#bulkImport").on('change', function( e ){
    $("#fileSizeModule").css("display","block");
    var fileSize = e.currentTarget.files[0].size;
    var totalNum=Math.round(Number(fileSize)/1024);
    $("#myModal_import").find("form input[name='fileSize']").val("大约"+totalNum+"KB");
});

//批量导入 保存
$("#myModal_import").on("click",".saveBtn",function(){
    var fileObj = document.getElementById("bulkImport").files[0]; // js 获取文件对象
    var name = fileObj.name;
    var url="/batchImportEastQuest/import";

    var form = new FormData(); // FormData 对象
    form.append("file", fileObj); // 文件对象

    var xhr;
    xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
    xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
    xhr.onload = uploadComplete2; //请求完成
    xhr.onerror =  uploadFailed2; //请求失败

    xhr.upload.onprogress = progressFunction2;//【上传进度调用方法实现】
    xhr.upload.onloadstart = function(){//上传开始执行方法
        ot = new Date().getTime();   //设置上传开始时间
        oloaded = 0;//设置上传开始时,以上传的文件大小为0
    };
    xhr.send(form); //开始上传,发送form数据

    //显示进度条
    $("#progressModule").css("display","block");
});

//上传成功响应
function uploadComplete2(evt){
    //服务断接收完文件返回的结果
    //console.log(evt);
    parent.layer.msg('批量导入成功!', {icon: 1});
    $("#progressModule").css("display","none");//隐藏进度条
    //关闭模态框
    $("#myModal_import").find(".modal-header .sr-only").click();
    var pageNum=$("b.presentPage").html();
    goPage(pageNum);
}
//上传失败
function uploadFailed2(evt){
    parent.layer.msg("导入失败");
}
//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction2(evt){
    // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
    if (evt.lengthComputable){
        $("#progressBar").css("width",Math.round(evt.loaded / evt.total * 100) + "%");
        $("#progressBar").html(Math.round(evt.loaded / evt.total * 100) + "%");
    }
    var nt = new Date().getTime();//获取当前时间
    var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
    ot = new Date().getTime(); //重新赋值时间,用于下次计算
    var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
    oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算
}

代码参考了:https://www.cnblogs.com/007sx/p/7520529.html

 

进度条优化

优化点:

之前的进度条过于真实,前端数据处理完成,没有考虑后端数据是否处理完。这样一旦后端出错导致前端操作失败,而前端进度条又走到底了,很容易给用户错误的引导。

本次改进,前端进度条人为设置最大值为98%,直到收到后端处理完成的信息后,再将进度条走到100%。

这样操作需要后端同事配合。万一你遇到的同事,死活不给你返回信息,你就只能退而求其次将就了。

 

代码

html

<form class='form-horizontal' id="myModal_add_form">
    <div class='form-group'>
        <label class='col-sm-2 control-label'>上传图像:</label>
        <div class='col-sm-10'>
            <input type="file" class="newFile"/>
            <input type="hidden" name="newFileMsg" data-name=""/>
            <input type="hidden" name="userId"/>
            <input type="hidden" name="faceId"/>
        </div>
    </div>
    <div class='form-group' style="display: none;" id="myModal_add_progressBar_Module">
        <label class='col-sm-2 control-label'>上传进度:</label>
        <div class='col-sm-10'>
            <div class="progress">
                <div class="progress-bar" id="myModal_add_progressBar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="width:0;" ></div>
            </div>
        </div>
    </div>
</form>

js

//图片上传
    $(".newFile").on('change', function(e){
        var userName=$(this).parents(".modal-content").find("input[name='name']").val();
        if(userName == ""){
            parent.layer.msg("必须先填写姓名!");
            document.getElementById("myModal_add_form").reset();
            return 
        }else{
            if(Math.round(Number(e.currentTarget.files[0].size)/1024) > 10240){
                parent.layer.msg("图片太大,请压缩大小后上传!图片最大 10 MB!");
                document.getElementById("myModal_add_form").reset();
                return 
            }else{
                var activityId = $("#searchForm").find("select[name='activeId']").val();
                var fileObj = e.currentTarget.files[0]; // js 获取文件对象
                var name = e.currentTarget.files[0].name;
                $(".newFile").parents("div.col-sm-10").find("input[name='newFileMsg']").attr("data-name",name);
                var url="/faceRecognition/activityManage/uploadImg?name="+userName+"&activityId="+activityId;
                
                var form = new FormData(); // FormData 对象
                form.append("file", fileObj); // 文件对象
                
                var xhr;
                xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
                xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
                
                xhr.onload = uploadComplete; //请求完成
                xhr.onerror =  uploadFailed; //请求失败
                
                xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
                xhr.upload.onloadstart = function(){//上传开始执行方法
                    ot = new Date().getTime();   //设置上传开始时间
                    oloaded = 0;//设置上传开始时,以上传的文件大小为0
                };
                xhr.send(form); //开始上传,发送form数据
                
                //显示进度条
                $("#myModal_add_progressBar_Module").css("display","block");
            }
        }
    });

    //上传成功响应
    function uploadComplete(evt){
        //服务器接收完文件返回的结果
        var res=JSON.parse(evt.target.responseText);
        if(res.code == 0){
            //上传成功
            $(".newFile").parents("div.col-sm-10").find("input[name='newFileMsg']").val(res.data.url);
            $(".newFile").parents("div.col-sm-10").find("input[name='userId']").val(res.data.id);
            $(".newFile").parents("div.col-sm-10").find("input[name='faceId']").val(res.data.faceId);
            
            //进度条设置为100%;
            $("#myModal_add_progressBar").css("width","100%");
            $("#myModal_add_progressBar").html("100%");
        }
    }
    //上传失败
    function uploadFailed(evt){
        parent.layer.msg("上传失败");
    }
    //上传进度实现方法,上传过程中会频繁调用该方法
    function progressFunction(evt) {
        // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
        if (evt.lengthComputable) {
            //进度条限制 上传时永远不能达到100% 最大98% 除非收到后端返回值 才设置为100%
            $("#myModal_add_progressBar").css("width", Math.floor(evt.loaded / evt.total * 100)-2 + "%");
            $("#myModal_add_progressBar").html(Math.floor(evt.loaded / evt.total * 100)-2 + "%");
        }
        var nt = new Date().getTime();//获取当前时间
        var pertime = (nt - ot) / 1000; //计算出上次调用该方法时到现在的时间差,单位为s
        ot = new Date().getTime(); //重新赋值时间,用于下次计算
        var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
        oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算
    }

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Irene1991

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值