首页 > 代码库 > Ext4.2结合Spring MVC实现文件上传显示进度

Ext4.2结合Spring MVC实现文件上传显示进度

1.实现原理:

  在大文件上传时显示上传进度是很有必要的,不能让用户感觉到陷入无穷的等待中,或感觉程序已经卡死。为此我们可以在session中存一个上传进度的变量,在文件上传的过程中实时的去修改这个值,这就需要在后台重写Spring MVC自带的上传解析类,每上传一定的字节数就修改一下session中的进度,在前台通个AJAX请求每隔一定的时间去获取这个值显示给用户,这样就达到了显示上传进度的需求,不过这样频繁的请求服务器无疑是增加了服务器的压力,在没有使用任何第三方上传组件的情况下只能如此。

2.测试结果:

   没有出现任何内存溢出或奔溃的情况。

   前台效果和后台打印日志:

   技术分享技术分享

 3.代码

 ①CustomMultipartResolver.java,Spring默认的文件上传类是CommonsMultipartResolver,我们需要自定义一个类CustomMultipartResolver继承它.

技术分享
package com.upload;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileItemFactory;import org.apache.commons.fileupload.FileUpload;import org.apache.commons.fileupload.FileUploadBase;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.springframework.web.multipart.MaxUploadSizeExceededException;import org.springframework.web.multipart.MultipartException;import org.springframework.web.multipart.MultipartHttpServletRequest;import org.springframework.web.multipart.commons.CommonsMultipartResolver;public class CustomMultipartResolver extends CommonsMultipartResolver {        private HttpServletRequest request;    protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {        ServletFileUpload upload = new ServletFileUpload(fileItemFactory);        if (request != null) {            HttpSession session = request.getSession();            MyProgressListener uploadProgressListener = new MyProgressListener(session);            upload.setProgressListener(uploadProgressListener);        }        return upload;    }         public MultipartHttpServletRequest resolveMultipart(            HttpServletRequest request) throws MultipartException {        this.request = request;// 获取到request,要用到session        return super.resolveMultipart(request);    }         @Override    public MultipartParsingResult parseRequest(HttpServletRequest request)            throws MultipartException {        String encoding = determineEncoding(request);        FileUpload fileUpload = prepareFileUpload(encoding);        //设置监听器        MyProgressListener progressListener = new MyProgressListener(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);        }    } }
View Code

 ②spring-servlet.xml,XML配置

技术分享
<!-- 文件上传配置 -->    <!-- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">           <property name="maxUploadSize" value="http://www.mamicode.com/1048576000"/>           <property name="maxInMemorySize" value="http://www.mamicode.com/4096"/>           <property name="defaultEncoding" value="http://www.mamicode.com/UTF-8"></property>    </bean>     -->    <bean id="multipartResolver" class="com.upload.CustomMultipartResolver">           <property name="maxUploadSize" value="1048576000"/>           <property name="maxInMemorySize" value="4096"/>           <property name="defaultEncoding" value="UTF-8"></property>    </bean> 
View Code

③MyProgressListener.java,文件上传监听器,需要实现ProgressListener接口

技术分享
package com.upload;import javax.servlet.http.HttpSession;import org.apache.commons.fileupload.ProgressListener;public class MyProgressListener implements ProgressListener {        private HttpSession session;           public MyProgressListener() {             }    public MyProgressListener(HttpSession session) {        this.session = session;        ProgressEntity ps = new ProgressEntity();        session.setAttribute("upload_ps", ps);    }     public void setSession(HttpSession session){        this.session = session;    }    @Override    public void update(long pBytesRead, long pContentLength, int pItems) {        ProgressEntity ps = (ProgressEntity) session.getAttribute("upload_ps");        ps.setpBytesRead(pBytesRead);        ps.setpContentLength(pContentLength);        ps.setpItems(pItems);            //更新        session.setAttribute("upload_ps", ps);       // System.out.println("当前进度:"+ps.getpBytesRead());    }}
View Code

 ④ProgressEntity.java 包含上传信息的实体

技术分享
package com.upload;public class ProgressEntity {    private long pBytesRead = 0L;   //到目前为止读取文件的比特数     private long pContentLength = 0L;    //文件总大小     private int pItems;                //目前正在读取第几个文件     public long getpBytesRead() {        return pBytesRead;    }    public void setpBytesRead(long pBytesRead) {        this.pBytesRead = pBytesRead;    }    public long getpContentLength() {        return pContentLength;    }    public void setpContentLength(long pContentLength) {        this.pContentLength = pContentLength;    }    public int getpItems() {        return pItems;    }    public void setpItems(int pItems) {        this.pItems = pItems;    }    @Override    public String toString() {        return "ProgressEntity [pBytesRead=" + pBytesRead + ", pContentLength="                + pContentLength + ", pItems=" + pItems + "]";    }}
View Code

⑤Action中的方法,上传方法任然不用变,还是原来的Spring上传方法,只需修改XML中的上传解析器.改成前面自定义的即可,增加一个获取上传进度的方法。SuccessBean是封装了返回前台的信息:包含success和msg两个字段。

技术分享
@ResponseBody    @RequestMapping(value = "/getProgress", method = RequestMethod.GET)    public SuccessBean getProgress(HttpServletRequest request, HttpServletResponse response){        if(request.getSession().getAttribute("upload_ps")==null){             return new SuccessBean(true,"0");        }        ProgressEntity ps = (ProgressEntity)request.getSession().getAttribute("upload_ps");        Double percent = 0d;        if(ps.getpContentLength() != 0L){            percent = (double)ps.getpBytesRead()/(double)ps.getpContentLength()*1.0d;  //百分比            if(percent != 0d){                DecimalFormat df = new DecimalFormat("0.00");                percent = Double.parseDouble(df.format(percent));            }        }       logger.info("当前上传进度:" + percent.toString());       return new SuccessBean(true, percent.toString());    }
View Code

 ⑥前台就更简单了,只需一个FormPanel添加一个filefield组件,在表单提交后同时启动定时任务,每隔1秒从后台获取一下进度显示出来即可。

Ext4.2结合Spring MVC实现文件上传显示进度