基于SpringMVC实现文件异步上传进度显示

转载:https://blog.csdn.net/cyh1111/article/details/52960233

实现

实现带进度条的文件上传一般都是服务器端计算文件上传进度,客户端轮询读取显示的方式。

Commons-fileupload组件自带了文件上传进度的监听器,类FileUploadBase提供了它的set方法。

SpringMVC没有实现监听器,所以如果要监听的话得自己扩展CommonsMultipartResolver类,加入代码设置自己实现的监听器

ProgressListener是一个接口,我们需要自己实现它的update方法,参数pBytesRead表示已经上传到服务器的字节数,pContentLength表示所有文件的总大小,pItems表示第几个文件

1、实现ProgressListener

FileUploadProgressListener实现ProgressListener,将上传进度保存到session中。

使用注解

@Component
public class FileUploadProgressListener implements ProgressListener {

    private HttpSession session;

    @Override
    public void update(long bytesRead, long contentLength, int items) {
        //设置上传进度
        ProgressBean progress = new ProgressBean(bytesRead, contentLength, items); 
        //将上传进度保存到session中
        session.setAttribute("progress", progress); 
    }

    public void setSession(HttpSession session){
        this.session = session;
    }
}

2、实现MultipartResolver

CustomMultipartResolver继承CommonsMultipartResolver,需要在每一次上传请求中设定处理上传进度的监听器,并处理文件上传。

将第一步中FileUploadProgressListener注入进来

public class CustomMultipartResolver extends CommonsMultipartResolver {

    //FileUploadProgressListener 自动注入
    @Resource
    private FileUploadProgressListener progressListener;

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

        //FileUploadProgressListener中注入session
        progressListener.setSession(request.getSession());

        fileUpload.setProgressListener(progressListener);

        try {
            List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
            return parseFileItems(fileItems, encoding);

        } catch (FileUploadBase.SizeLimitExceededException ex) {
            throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
        } catch (FileUploadException ex) {
            throw new MultipartException("Could not parse multipart servlet request", ex);
        }
    }
}

3、Progress 实体类

public class ProgressBean {

    private long bytesRead;

    private long contentLength;

    private long items;

    public ProgressBean(long bytesRead, long contentLength, long items) {
        super();
        this.bytesRead = bytesRead;
        this.contentLength = contentLength;
        this.items = items;
    }

    public long getBytesRead() {
        return bytesRead;
    }

    public void setBytesRead(long bytesRead) {
        this.bytesRead = bytesRead;
    }

    public long getContentLength() {
        return contentLength;
    }

    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }

    public long getItems() {
        return items;
    }

    public void setItems(long items) {
        this.items = items;
    }

    @Override
    public String toString() {
        return "ProgressBean [bytesRead=" + bytesRead + ", contentLength="
                + contentLength + ", items=" + items + "]";
    }

}

4、SpringMVC Controller方法

/**
     * 异步上传处理
     * @param request
     * @param response
     * @param file
     * @return 返回上传文件相对路径及名称
     * @throws IOException
     */
    @RequestMapping(value="/file/upload", produces = "text/json;charset=UTF-8")
    @ResponseBody
    public String uploadFileHandler(HttpServletRequest request, @RequestParam("file") MultipartFile file){

        //上传文件每日单独保存
        String path = "/upload/"+DateUtil.getNowDate()+"/";

        if (file.getSize() > 0) {
            //获取绝对路径
            String uploadPath = request.getSession().getServletContext().getRealPath(path);
            try {
                //创建目标文件
                File targetFile = new File(uploadPath, file.getOriginalFilename());
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }

                file.transferTo(targetFile);
                JSON.toJSONString(path+file.getOriginalFilename());
            } catch (Exception e) {

            }
        }
        return null;
    }

5、配置CustomMultipartResolver

在SpringMVC配置文件中配置CustomMultipartResolver,支持文件上传

<!-- 支持上传文件 -->  
    <bean id="multipartResolver" class="com.lead.sy.web.upload.CustomMultipartResolver"/>  

6、上传页面

 <div class="modal-body">
                <div class="form-group" id="passwordDiv">
                    <label>选择营业执照照片</label> 
                    <input class="form-control" type="file" id="uploadFile">
                </div>
                <div class="form-group">
                    <input id="btnUpload" type="button"  class="btn btn-success" value="上传" />
                </div>
   </div>

上传控制JS代码

<script>
    $(function () {
        // 默认上传按钮不可用
        $("#btnUpload").attr("disabled", true);

        // 弹出上传Model
        $("#activeUpload").click(function(){
            $("#uploadModal").modal("show");
        })

        // 上传按钮点击事件
        $("#btnUpload").click(function() {
            //上传按钮修改为可用
            $(this).attr("disabled", true);
            uploadFunction();
        })

        // 文件修改时
        $("#uploadFile").change(function() {
            $("#btnUpload").val("上传");
            var file = $(this).prop("files");
            if (file.length != 0) {
                $("#btnUpload").attr("disabled", false);
            }
        });

        //文件上传
        function uploadFunction() {
            var uploadFile = $("#uploadFile").get(0).files[0]; //获取文件对象

            // FormData 对象
            var form = new FormData();
            form.append("file", uploadFile); // 文件对象
            var uploadUrl = "<%=path%>/file/upload";//异步上传地址
            $.ajax({
                cache: false,
                type: "POST",
                url: uploadUrl,
                contentType: false, 
                processData: false, 
                data: form,
                xhr: function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
                    myXhr = $.ajaxSettings.xhr();
                    if(progressFunction && myXhr.upload) { //检查进度函数和upload属性是否存在
                        //绑定progress事件的回调函数
                        myXhr.upload.addEventListener("progress",progressFunction, false);
                    }
                    return myXhr; //xhr对象返回给jQuery使用
                },
                error: function(request) {
                    alert("Connection error");
                },
                success: function(data) {
                    $("input[name=companyLicenseImg]").val(data);
                    $("#licenseImg").attr("src","<%=path%>"+data); //将后台返回图片路径设置给IMG,显示图片
                    $("#licenseImg").attr("width","100"); 
                    $("#activeUpload").val("重新上传");

                    $("#btnUpload").attr("disabled", false);
                    $("#btnUpload").val("上传");
                    $("#uploadModal").modal("hide");
                }
            });
        }

        //进度条控制
        function progressFunction(evt) {
            if (evt.lengthComputable) {
                var completePercent = Math.round(evt.loaded / evt.total * 100)+ "%";
                $("#btnUpload").val("正在上传,进度:" + completePercent);
            }
        }
    });
</script>

猜你喜欢

转载自blog.csdn.net/wellxielong/article/details/81449777