zoukankan      html  css  js  c++  java
  • 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="1048576000"/>  
             <property name="maxInMemorySize" value="4096"/>  
             <property name="defaultEncoding" value="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秒从后台获取一下进度显示出来即可。

  • 相关阅读:
    20160813上午训练记录
    [bzoj 2159]Crash的文明世界
    【娱乐】高端小游戏Manufactoria
    【教程】如何正确的写一个Lemon/Cena的SPJ(special judge)
    [CF]codeforces round#366(div2)滚粗记
    洛谷 [P3265] 装备购买
    POJ 1830 开关问题
    洛谷 [P4035] 球形空间生成器
    BZOJ 2973 入门OJ4798 石头游戏
    洛谷 [P1939] 矩阵加速数列
  • 原文地址:https://www.cnblogs.com/zhougaojun/p/4200460.html
Copyright © 2011-2022 走看看