文件上传进度条实现(两种方法)

方法一:纯js的实现

  • JS

/**
 * 文件上传
 */
function fileupload() {
    swal({
        title: "提示",
        text: "确认上传该文件?",
        type: "info",
        showCancelButton: true,
        confirmButtonColor: "#CD6600",
        confirmButtonText: "上传",
        cancelButtonText: "取消",
        closeOnConfirm: false,
        closeOnCancel: false
    }, function (isConfirm) {
        if (isConfirm) {
            swal({
                title: "<small>上传中。。。</small>",
                text: "<progress id=\"progressBar\" value=\"0\" max=\"100\" style=\"width: 240px;\"></progress>\n" +
                    "            <span id=\"percentage\"></span><span id=\"time\"></span>",
                html: true
            });
            var file = $('#multipartFile')[0].files[0];
            var url = "/FtpHandle/upload"; // 接收上传文件的后台地址 /这里在后台做了跨域处理

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

            xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
            xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
            xhr.onload = uploadComplete; //请求完成
            xhr.onerror = uploadFailed; //请求失败
            xhr.setRequestHeader("Authrorization",window.localStorage.getItem("Authrorization"));
            xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
            xhr.upload.onloadstart = function () {//上传开始执行方法
                ot = new Date().getTime();   //设置上传开始时间
                oloaded = 0;//设置上传开始时,以上传的文件大小为0
            };

            xhr.send(formData); //开始上传,发送form数据
        } else {
            //取消
            swal({
                title: "提示",
                text: "取消上传",
                type: "success"
            })
        }
    })
}

//上传成功响应
function uploadComplete(evt) {
    //服务断接收完文件返回的结果

    var data = JSON.parse(evt.target.responseText);
    if (data.flag == true) {
        swal({
            title: "提示",
            text: "上传成功",
            type: "success"
        }, function () {
            fileList(1)
        })
    } else {
        swal("提示", Result.message, "error")
    }

}

//上传失败
function uploadFailed(evt) {
    swal("提示", "请重试", "error")
}

//取消上传
function cancleUploadFile() {
    xhr.abort();
}


//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction(evt) {
    var progressBar = document.getElementById("progressBar");
    var percentageDiv = document.getElementById("percentage");
    // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
    if (evt.lengthComputable) {//
        progressBar.max = evt.total;
        progressBar.value = evt.loaded;
        percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
    }
    var time = document.getElementById("time");
    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.innerHTML = ',速度:' + speed + units + ',剩余时间:' + resttime + 's';
    if (bspeed == 0) time.innerHTML = '上传已取消';
}
  • HTML
 <div class="container">
        <div class="content bg-blue">
            <div class="services-caption">
<!--                <input type="file" id="multipartFile" name="multipartFile"/>-->
<!--                <a href="javascript:void(0);" class="file">-->
<!--                    <input type="file" name="multipartFile" id="multipartFile">选择文件-->
<!--                </a>-->
                <a href="javascript:void(0);" class="upload">选择文件 > <span>未选择任何文件</span>
                    <input class="replyFileid" type="file" name="multipartFile" id="multipartFile" multiple="multipartFile"  onchange="getfilename(this);"/>
                </a>
            </div>
<!--            <progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>-->
<!--            <span id="percentage"></span><span id="time"></span>-->
            <div class="progress">
                <div id="progress" class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0"
                     aria-valuemax="100" style="width: 1%;">
                    60%
                </div>
            </div>
            <a href="javascript:void(0);" onclick="return fileupload()"><h4>上传</h4></a>
        </div>
    </div>

方法二:后端实现(重写)

  • 写监听器(实现 ProgressListener 接口)
package club.zby.ftp.Service;

import org.apache.commons.fileupload.ProgressListener;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpSession;


/**
 * @Author: 赵博雅
 * @Date: 2019/11/18 17:44
 */

public class FileUploadProgressListener implements ProgressListener {

    @Autowired
    private HttpSession session;


    public void setSession(HttpSession session) {
        this.session = session;
        System.out.println("初始化");
        session.setAttribute("upload_percent", 0);
    }

    @Override
    public void update(long pBytesRead, long pContentLength, int pItems) {
        int percent = (int) (pBytesRead * 100.0 / pContentLength);
        System.out.println("当前状态:" + percent + "%");
        session.setAttribute("upload_percent", percent);
    }

}


  • 自定义解析器(继承CommonsMultipartResolver类重写parseRequest方法)
package club.zby.ftp.Service;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @Author: 赵博雅
 * @Date: 2019/11/18 18:06
 */

public class CustomMultipartResolver extends CommonsMultipartResolver {

    @Autowired
    private FileUploadProgressListener listener;

    @Override
    protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
        String encoding = determineEncoding(request);
        FileUpload fileUpload = prepareFileUpload(encoding);

        fileUpload.setProgressListener(listener);
        listener.setSession(request.getSession());
        System.out.println("session:" + request.getSession().getAttribute("upload_percent"));
        try {
            List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
            return parseFileItems(fileItems, encoding);
        }catch (FileUploadException ex) {
            throw new MultipartException("Failed to parse multipart servlet request", ex);
        }
    }
}
  • 配置解析器
  • 控制器
@CrossOrigin(origins = "*")
    @RequestMapping(value = "/uploads", method = RequestMethod.POST)
    @ApiOperation(value="ftp文件上传测试", notes="ftp文件上传测试--上传地址:E:\\ddd")
    @ResponseBody
    public void upload(@RequestParam(value = "file") MultipartFile file){
        try {
            Calendar cal = Calendar.getInstance();
            Integer year = cal.get(Calendar.YEAR);
            Integer month = cal.get(Calendar.MONTH)+1;
            Integer day = cal.get(Calendar.DAY_OF_MONTH);

            String destPath = resourcePath + File.separator + year + File.separator + month + File.separator + day + File.separator;
            String destUrl = "127.0.0.1:10003" + "/" + year + "/" + month + "/" + day + "/";

            logger.info("目标路径:"+destPath);
            File destFile = new File(destPath);
            if(!destFile.exists()){
                logger.info("目标路径不存在,去创建");
                destFile.mkdirs();
            }

            //获取文件后缀
            String sourceFileName=file.getOriginalFilename();
            String suffix=sourceFileName.substring(sourceFileName.lastIndexOf("."),sourceFileName.length());
            logger.info("上传文件名称:"+sourceFileName);

            //写入目的文件
            String destFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;
            file.transferTo(new File(destPath + destFileName));

//            return destUrl + destFileName;
        }catch (Exception e){
            e.printStackTrace();
            logger.debug(e.getMessage());
//            return "";
        }
    }

    @CrossOrigin(origins = "*")
    @RequestMapping(value = "/uploadStatus")
    @ApiOperation(value="ftp文件上传进度测试", notes="ftp文件上传进度测试")
    @ResponseBody
    public Integer uploadStatus(HttpServletRequest request){
        HttpSession session = request.getSession();
        Object percent = session.getAttribute("upload_percent");
        return null != percent ? (Integer) percent : 0;
    }
@CrossOrigin(origins = "*")是为了在本地测试环境下解决跨域问题
  • 测试页面
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>测试</title>
</head>
<body>
<form id="form" action="/upload" method="POST" enctype="multipart/form-data" οnsubmit="return upload();">
    <input type="file" name="file"/>
    <br/>
    <input type="submit" value="提交"/>
</form>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/jquery.form/4.2.2/jquery.form.min.js"></script>
<script>
    function upload() {
        $("#form").ajaxSubmit(function(message) {
 
        });
 
        // 500ms 打印一次当前的上传进度
        setInterval(function () {
            $.ajax({
                type:"get",
                dataType: 'json',
                url:"/uploadStatus",
                success: function(result){
                    console.log(result)
                }
            });
        }, 500);
 
        return false;
    }
</script>
</html>
由于本地运行,速度比较快

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注