zoukankan      html  css  js  c++  java
  • commons-fileupload实现上传进度条的显示

      本文将使用   apache fileupload   ,spring MVC   jquery 实现一个带进度条的多文件上传, 由于fileupload 的局限,暂不能实现每个上传文件都显示进度条,只能实现一个总的进度条

    优点:不用引入第三方的组件(如js框架,flash等)

    缺点:如果同时上传多个文件,由于apache fileupload API的限制,只能显示一个总的进度条

    1.引入环境所需要的jar包

    引入上传工具类jar包

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>            

    引入mvc处理json数据jar包(@requestbody&@responsebody)

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.1</version>
    </dependency> 

    2.jsp页面

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.js"></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
    <link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
    <script type="text/javascript">  
    $(document).ready(function(){  
         $('#subbut').bind('click',  
                function(){         
                    $('#fForm').submit();  
                    
                    var eventFun = function(){  
                        $.ajax({  
                            type: 'GET',  
                            url: '${pageContext.request.contextPath}/test/process.action',  
                            data: {},  
                            dataType: 'json',  
                            success : function(data){  
                                    $("#fff").html("上传进度:"+data.show);
                                    $( "#proBar" ).progressbar({
                                        value: data.rate
                                      });
                                    if(data.rate == 100){  
                                        window.clearInterval(intId);  
                                        alert("上传完成");
                                    }     
                    }});};  
                    var intId = window.setInterval(eventFun,100);  
        });             
    });  
    </script>  
    <title>Insert title here</title>
    </head>
    <body>
          <form id='fForm'   action="${pageContext.request.contextPath}/test/testbar.action" encType="multipart/form-data"  method="post" target="uploadf">  
                             <div>  
                                <label>上传文件:</label>  
                                <div>  
                                    <input type="file"  name="file" style="550">  
                                </div>  
                              
                                <label id="fff"></label>  
                                <div>  
                                    <div style="50%">  
                                        <div  id = 'proBar'></div>  
                                    </div>  
                                </div>  
                            </div>  
                             <div >  
                                <div >  
                                <button type="button" id="subbut" >submit</button>  
                                </div>  
                            </div>  
        </form>  
        <iframe name="uploadf" style="display:none"></iframe>   
    </body>
    </html>

    这里注意需要引入js和css,如果需要更换进度条的样式,可以引入其他的css(如bootstarp等)

    3.后台的实现

    import java.io.File;
    import java.util.Iterator;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileItemFactory;
    import org.apache.commons.fileupload.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.log4j.Logger;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;
    @Controller
    @RequestMapping("/test")
    public class FileUploadController {
        
        private final    Logger log = Logger.getLogger(FileUploadController.class);  
        
        /** 
         * upload  上传文件 
         */  
        @RequestMapping(value = "/testbar.action", method = RequestMethod.POST)  
        public ModelAndView upload(HttpServletRequest request,HttpServletResponse response) throws Exception {  
            final HttpSession hs = request.getSession();  
            ModelAndView mv = new ModelAndView();  
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
            if(!isMultipart){  
                return mv;  
            }  
            // Create a factory for disk-based file items  
            FileItemFactory factory = new DiskFileItemFactory();  
      
            // Create a new file upload handler  
            ServletFileUpload upload = new ServletFileUpload(factory);  
            //解决上传文件名的中文乱码
            upload.setHeaderEncoding("UTF-8"); 
            
            upload.setProgressListener(new ProgressListener(){  
                   public void update(long pBytesRead, long pContentLength, int pItems) {  
                       ProcessInfo pri = new ProcessInfo();  
                       pri.itemNum = pItems;  
                       pri.readSize = pBytesRead;  
                       pri.totalSize = pContentLength;  
                       pri.show = pBytesRead+"/"+pContentLength+" byte";  
                       pri.rate = Math.round(new Float(pBytesRead) / new Float(pContentLength)*100);  
                       hs.setAttribute("proInfo", pri);  
                   }  
                });  
            //     Parse the request  
            List items = upload.parseRequest(request);  
          //   Process the uploaded items  
          Iterator iter = items.iterator();  
          while (iter.hasNext()) {  
              FileItem item = (FileItem) iter.next();  
              if (item.isFormField()) {  
                  String name = item.getFieldName();  
                  String value = item.getString("utf-8");  
                  System.out.println("this is common feild!"+name+"="+value);  
              } else {  
                  System.out.println("this is file feild!");  
                   String fieldName = item.getFieldName();  
                      String fileName = item.getName().substring(item.getName().lastIndexOf("\")+1);;  
                      String contentType = item.getContentType();  
                      boolean isInMemory = item.isInMemory();  
                      long sizeInBytes = item.getSize();  
                      File uploadedFile = new File("c://"+fileName);  
                      item.write(uploadedFile);  
                     
              }  
          }  
        
            return mv;  
        }  
          
          
        /** 
         * process 获取进度 
         */  
        @RequestMapping(value = "/process.action", method = RequestMethod.GET)    
        public @ResponseBody Object process(HttpServletRequest request,HttpServletResponse response) throws Exception {  
            return ( ProcessInfo)request.getSession().getAttribute("proInfo");  
        }   
        //精度条pojo
        class ProcessInfo{  
            public long totalSize = 1;  
            public long readSize = 0;  
            public String show = "";  
            public int itemNum = 0;  
            public int rate = 0;  
        }  
    }

    4.SpringMVC中servletFileUpload.parseRequest(request)解析为空获取不到数据问题

    问题产生的原因

    先看一下springmvc中上传的配置

      <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
                <property name="defaultEncoding" value="UTF-8" />  
                <property name="maxUploadSize" value="2000000000" />  
      </bean>  

     再看看controller中使用

    方式一

     public void upload2(HttpServletRequest request) {  
                // 转型为MultipartHttpRequest  
                try {  
                    MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;  
                    List<MultipartFile> fileList = multipartRequest.getFiles("file");  
                    for (MultipartFile mf : fileList) {  
                        if(!mf.isEmpty()){  
                              
                        }  
                    }  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
                  
            }  

    方式二

     public String upload(HttpServletRequest request,  
                    @RequestParam(value = "file") MultipartFile[] files) {  
                try {  
                    for (MultipartFile mf : files) {  
                        if(!mf.isEmpty()){  
                              
                        }  
                    }  
          
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
                return "upload";  
            }  

    这里springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置的CommonsMultipartResolver这个转换器里面.他的转换器里面就是调用common-fileupload的方式解析,然后再使用parseFileItems()方法封装成自己的文件对象.大家应该发现了上面的这句代码,已经使用过fileUpload解析过request了,你在Controller里面接收到的request都已经是解析过的,你再次使用upload进行解析获取到的肯定是空,这个就是问题的所在

    解决方式一(以上案例就是用此解决方法)

    1.删除mvc里面上传的配置

    <!--         <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> -->
    <!--          指定所上传文件的总大小不能超过200KB。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->   
    <!--         <property name="maxUploadSize" value="200000"/>   -->
    <!--         </bean> -->

     2.在控制器里面自己完成request的解析(当然上面spring MVC提供的两种方法是不能用的,所有上传的地方都需要自己做处理)

    public void upload3(HttpServletRequest request) {  
                DiskFileItemFactory factory = new DiskFileItemFactory();  
                ServletFileUpload upload = new ServletFileUpload(factory);  
                try {  
                    List<FileItem> list = upload.parseRequest(request);  
                    for(FileItem item : list){  
                        if(item.isFormField()){  
                              
                        }else{  
                            //item.write(new File(""));  
                        }  
                    }  
                } catch (FileUploadException e) {  
                    e.printStackTrace();  
                }  
                  
            }  

    解决方式二(重写listener)

     1.创建状态pojo

    public class Progress {
        
         public long totalSize = 1;  
         public long readSize = 0;  
         public String show = "";  
         public int itemNum = 0;  
         public int rate = 0;
         
        
        public void setTotalSize(long totalSize) {
            this.totalSize = totalSize;
        }
        
        public void setReadSize(long readSize) {
            this.readSize = readSize;
        }
        public String getShow() {
            return readSize+"/"+totalSize+" byte";
        }
        
        public int getItemNum() {
            return itemNum;
        }
        public void setItemNum(int itemNum) {
            this.itemNum = itemNum;
        }
        public int getRate() {
            return Math.round(new Float(readSize) / new Float(totalSize)*100);
        }
    }

    2.写自己的listener

    import javax.servlet.http.HttpSession;
    
    import org.apache.commons.fileupload.ProgressListener;
    
    public class FileUploadListener implements ProgressListener{
    
        
            private HttpSession session;  
          
            public void setSession(HttpSession session){  
                this.session=session;  
                Progress status = new Progress();  
                session.setAttribute("status", status);  
            }  
          
            /*  
             * pBytesRead 到目前为止读取文件的比特数 pContentLength 文件总大小 pItems 目前正在读取第几个文件  
             */  
            public void update(long pBytesRead, long pContentLength, int pItems) {  
                Progress status = (Progress) session.getAttribute("status");                         
                status.setReadSize(pBytesRead);
                status.setTotalSize(pContentLength);
                status.setItemNum(pItems);
            } 
    
    }

    3.写自己的resolver

    public class CommonsMultipartResolverExt extends CommonsMultipartResolver{
    
         @Override  
            protected MultipartParsingResult parseRequest(HttpServletRequest request)  
                    throws MultipartException {  
                FileUploadListener listener = new FileUploadListener();  
                listener.setSession(request.getSession());
                String encoding = determineEncoding(request);  
                FileUpload fileUpload = prepareFileUpload(encoding);  
                fileUpload.setProgressListener(listener);  
                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);  
                }  
            }   
    }

    4.配置上传resolver

        <bean id="multipartResolver" class="com.fyh.www.common.CommonsMultipartResolverExt"></bean>

    5.测试

    @Controller
    @RequestMapping("/test2")
    public class FileUploadController2 {
        
        private final    Logger log = Logger.getLogger(FileUploadController2.class);  
        
        /** 
         * upload  上传文件 
         */  
        @RequestMapping(value = "/testbar.action", method = RequestMethod.POST)  
        public ModelAndView upload(HttpServletRequest request,HttpServletResponse response) throws Exception {  
            ModelAndView mv = new ModelAndView();
            MultipartHttpServletRequest multipartRequest=(MultipartHttpServletRequest) request;
            MultipartFile file = multipartRequest.getFile("file");
            
            InputStream inputStream = file.getInputStream();
            
            FileUtils.copyInputStreamToFile(inputStream, new File("e://"+file.getOriginalFilename()));
            
            
        
            return mv;  
        }  
          
          
        /** 
         * process 获取进度 
         */  
        @RequestMapping(value = "/process.action", method = RequestMethod.GET)    
        public @ResponseBody Object process(HttpServletRequest request,HttpServletResponse response) throws Exception {  
            return ( Progress)request.getSession().getAttribute("status");  
        }   
      
    }

    此方案在获取监控进度的同时并不因影响mvc原有上传方法的使用

    解决方式三(需要用到进度条的上传时,写独立的servlet,servlet+apache uploadfile  与springmvc互不干预)不建议用此方法

  • 相关阅读:
    Django-model聚合查询与分组查询
    Django-model基础
    tempalte模板
    Nginx配置TCP请求转发
    使用python调用email模块发送邮件附件
    将txt文本转换为excel格式
    Linux系统
    Aws云服务EMR使用
    SHELL打印两个日期之间的日期
    02-模板字符串
  • 原文地址:https://www.cnblogs.com/woms/p/6003099.html
Copyright © 2011-2022 走看看