zoukankan      html  css  js  c++  java
  • java FileUpload 组件上传文件

    Commons FileUpload

    Apache提供的一个组件,可以很方便的让我们处理客户端上传的文件,

    下载地址 http://commons.apache.org/proper/commons-fileupload/

    下载commons-fileupload.jar,还有其依赖包 commons-io.jar一同下载好,导入工程

    有点奇葩的是,在tomcat下已经把這个组建集成了,但是不能正常使用,其源码基本上是一样的。

    正确的包名应该是這个:org.apache.commons.fileupload.

    而不是org.apache.tomcat.util.http.fileupload.下面的

    最简单的使用

     1 protected void doPost(HttpServletRequest request,
     2             HttpServletResponse response) throws ServletException, IOException {
     3 
     4         ServletContext servletContext = this.getServletContext();
     5 
     6         // 指定保存文件的位置,放在WEB-INF目录下是为了保证系统的安全性
     7         String savePath = servletContext.getRealPath("/WEB-INF/upload");
     8         System.out.println("savePath=" + savePath);
     9 
    10         if (ServletFileUpload.isMultipartContent(request)) {
    11 
    12             try {
    13                 // 创建FileItem的工厂
    14                 DiskFileItemFactory factory = new DiskFileItemFactory();
    24                 // 创建一个FileItem的解析器,根据前面设置好的工厂得到
    25                 ServletFileUpload upload = new ServletFileUpload(factory);
    26 
    27                 // 解析出FIleItem项,parserRequest接收的类型是
    28                 // javax.servlet.http.HttpServletRequest
    29                 List<FileItem> items = upload.parseRequest(request);
    30 
    31                 // 遍历FileItem,检查是否为普通字符还是文件流
    32                 for (FileItem item : items) {
    33 
    34                     // 普通表单文字
    35                     if (item.isFormField()) {
    36                         // 表单上的name
    37                         String name = item.getFieldName();
    38                         // 表单上的value
    39                         String value = item.getString();
    40 
    41                         System.out.println("name=" + name
    42                                 + "   ----------   value=" + value);
    43 
    44                         // 数据库操作。。
    45                     } else {
    46                         // 文件一般从网络上传后存放到数据库,而原来的文件将采用不重复的命名方案存放
    47                         String fileName = item.getName();// 文件名,可能是带全路径的或者就是文件名
    48                         System.out.println("上传文件全路径:" + fileName);
    49                         fileName = fileName.substring(fileName
    50                                 .lastIndexOf("\") + 1);// IE
    51                                                         // 、Opera
    52                         System.out.println("上传文件名:" + fileName);
    53 
    54                         // 没有上传文件
    55                         if (fileName.equals("")) {
    56                             break;
    57                         }
    58                         InputStream in = item.getInputStream();
    59                         FileOutputStream fos = new FileOutputStream(savePath
    60                                 + "\" + fileName);
    61 
    62                         byte[] b = new byte[1024];
    63                         int len = 0;
    64                         while ((len = in.read(b)) != -1) {
    65                             fos.write(b, 0, len);
    66                         }
    67 
    68                         in.close();
    69                         fos.close();
    70 
    71                     }
    72                 }
    73 
    74             } catch (FileUploadException e) {
    75                 // TODO Auto-generated catch block
    76                 e.printStackTrace();
    77             }
    78 
    79         } else {
    80             response.getWriter().write("no multipart/form-data submit");
    81         }
    82     }
    83     

    设置一下高级的用法:

    修改默认设置,设置限制上传大小,返回当前上传进度。。

    protected void doPost(HttpServletRequest request,
                final HttpServletResponse response) throws ServletException,
                IOException {
            response.setContentType("text/html;charset=UTF-8");
            ServletContext servletContext = this.getServletContext();
    
            // 指定保存文件的位置,放在WEB-INF目录下是为了保证系统的安全性
            String savePath = servletContext.getRealPath("/WEB-INF/upload");
            System.out.println("savePath=" + savePath);
    
            if (ServletFileUpload.isMultipartContent(request)) {
    
                try {
                    // 创建FileItem的工厂
                    DiskFileItemFactory factory = new DiskFileItemFactory();
    
                    // 设置FileItem工厂的一些属性
                    File repository = (File) servletContext
                            .getAttribute("javax.servlet.context.tempdir"); // 得到用户临时文件夹
                    System.out.println("temp position:" + repository.getPath());
    
                    factory.setRepository(repository); // 设置临时的存储位置
                    factory.setSizeThreshold(1024 * 100);// 设置缓存大小为100kb,默认为10K,以字节为单位
    
                    // 创建一个FileItem的解析器,根据前面设置好的工厂得到
                    ServletFileUpload upload = new ServletFileUpload(factory);
                    // 设置允许上传的最大值,超出则拒绝上传
                    upload.setSizeMax(1024 * 1000);
                    // 设置上传时的进度条监听器
                    ProgressListener pListener = new ProgressListener() {
    
                        @Override
                        public void update(long pBytesRead, long pContentLength,
                                int pItems) {
                            try {
                                response.getWriter().write(
                                        "上传第"
                                                + pItems
                                                + "文件      上传进度:"
                                                + (pBytesRead * 1.0
                                                        / pContentLength * 100)
                                                + "%<br/>");
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    };
                    upload.setProgressListener(pListener);
    
                    // 解析出FIleItem项,parserRequest接收的类型是
                    // javax.servlet.http.HttpServletRequest
                    List<FileItem> items = upload.parseRequest(request);
    
                    // 遍历FileItem,检查是否为普通字符还是文件流
                    for (FileItem item : items) {
    
                        // 普通表单文字
                        if (item.isFormField()) {
                            // 表单上的name
                            String name = item.getFieldName();
                            // 表单上的value
                            String value = item.getString();
    
                            System.out.println("name=" + name
                                    + "   ----------   value=" + value);
    
                            // 数据库操作。。
    
                        } else {
                            // 文件一般从网络上传后存放到数据库,而原来的文件将采用不重复的命名方案存放,System.currentTime
                            String fileName = item.getName();// 文件名,可能是带全路径的或者就是文件名
                            System.out.println("上传文件全路径:" + fileName);
                            fileName = fileName.substring(fileName
                                    .lastIndexOf("\") + 1);// IE
                                                            // 、Opera
                            System.out.println("上传文件名:" + fileName);
    
                            // 没有上传文件
                            if (fileName.equals("")) {
                                break;
                            }
                            InputStream in = item.getInputStream();
                            FileOutputStream fos = new FileOutputStream(savePath
                                    + "\" + getFileName(fileName));
    
                            byte[] b = new byte[1024];
                            int len = 0;
                            while ((len = in.read(b)) != -1) {
                                fos.write(b, 0, len);
                            }
    
                            in.close();
                            fos.close();
    
                        }
                    }
    
                } catch (SizeLimitExceededException e1) {
                    response.getWriter().write("超出大小啦。。");
                } catch (FileUploadException e) {
                    response.getWriter().write("上传失败了。。");
                    e.printStackTrace();
                }
    
            } else {
                response.getWriter().write("no multipart/form-data submit");
            }
        }
    
        String getFileName(String fileName) {
            Date date = new Date(System.currentTimeMillis());
            String result = DateFormat.getDateInstance(DateFormat.SHORT).format(
                    date)
                    + "_" + fileName;
            return result;
        }
    這个组建的目录结构如图



    ServletFileUpload.isMultipartContent(request) 判断是否带有文件数据的表单

    其内部其实还是调用了request.getContentType()的方法的

    ServletUpload
    1     public static final boolean isMultipartContent(
    2             HttpServletRequest request) {
    3         if (!POST_METHOD.equalsIgnoreCase(request.getMethod())) {
    4             return false;
    5         }
    6         return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
    7     }

    FileUploadBase

     1   public static final boolean isMultipartContent(RequestContext ctx) {
     2         String contentType = ctx.getContentType();
     3         if (contentType == null) {
     4             return false;
     5         }
     6         if (contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART)) {
     7             return true;
     8         }
     9         return false;
    10     }

     //获取迭代器,效率最高的

    FileItemIterator  fIterator = upload.getItemIterator(request);

    //获取List集合,调用迭代器转换而来的

    List<FileItem> items = upload.parseRequest(request);

    //获取Map集合,调用list集合转换的

    parseParameterMap(request)

    迭代器实现过程:

     1   FileItemIteratorImpl(RequestContext ctx)
     2                 throws FileUploadException, IOException {
     3             if (ctx == null) {
     4                 throw new NullPointerException("ctx parameter");
     5             }
     6 
     7             String contentType = ctx.getContentType();
     8             if ((null == contentType)
     9                     || (!contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART))) {
    10                 throw new InvalidContentTypeException(
    11                         format("the request doesn't contain a %s or %s stream, content type header is %s",
    12                                MULTIPART_FORM_DATA, MULTIPART_MIXED, contentType));
    13             }
    14 
    15             InputStream input = ctx.getInputStream();
    16 
    17             @SuppressWarnings("deprecation") // still has to be backward compatible
    18             final int contentLengthInt = ctx.getContentLength();
    19 
    20             final long requestSize = UploadContext.class.isAssignableFrom(ctx.getClass())
    21                                      // Inline conditional is OK here CHECKSTYLE:OFF
    22                                      ? ((UploadContext) ctx).contentLength()
    23                                      : contentLengthInt;
    24                                      // CHECKSTYLE:ON
    25 
    26             if (sizeMax >= 0) {
    27                 if (requestSize != -1 && requestSize > sizeMax) {
    28                     throw new SizeLimitExceededException(
    29                         format("the request was rejected because its size (%s) exceeds the configured maximum (%s)",
    30                                 Long.valueOf(requestSize), Long.valueOf(sizeMax)),
    31                                requestSize, sizeMax);
    32                 }
    33                 input = new LimitedInputStream(input, sizeMax) {
    34                     @Override
    35                     protected void raiseError(long pSizeMax, long pCount)
    36                             throws IOException {
    37                         FileUploadException ex = new SizeLimitExceededException(
    38                         format("the request was rejected because its size (%s) exceeds the configured maximum (%s)",
    39                                 Long.valueOf(pCount), Long.valueOf(pSizeMax)),
    40                                pCount, pSizeMax);
    41                         throw new FileUploadIOException(ex);
    42                     }
    43                 };
    44             }
    45 
    46             String charEncoding = headerEncoding;
    47             if (charEncoding == null) {
    48                 charEncoding = ctx.getCharacterEncoding();
    49             }
    50 
    51             boundary = getBoundary(contentType);
    52             if (boundary == null) {
    53                 throw new FileUploadException("the request was rejected because no multipart boundary was found");
    54             }
    55 
    56             notifier = new MultipartStream.ProgressNotifier(listener, requestSize);
    57             try {
    58                 multi = new MultipartStream(input, boundary, notifier);
    59             } catch (IllegalArgumentException iae) {
    60                 throw new InvalidContentTypeException(
    61                         format("The boundary specified in the %s header is too long", CONTENT_TYPE), iae);
    62             }
    63             multi.setHeaderEncoding(charEncoding);
    64 
    65             skipPreamble = true;
    66             findNextItem();
    67         }
      1   private boolean findNextItem() throws IOException {
      2             if (eof) {
      3                 return false;
      4             }
      5             if (currentItem != null) {
      6                 currentItem.close();
      7                 currentItem = null;
      8             }
      9             for (;;) {
     10                 boolean nextPart;
     11                 if (skipPreamble) {
     12                     nextPart = multi.skipPreamble();
     13                 } else {
     14                     nextPart = multi.readBoundary();
     15                 }
     16                 if (!nextPart) {
     17                     if (currentFieldName == null) {
     18                         // Outer multipart terminated -> No more data
     19                         eof = true;
     20                         return false;
     21                     }
     22                     // Inner multipart terminated -> Return to parsing the outer
     23                     multi.setBoundary(boundary);
     24                     currentFieldName = null;
     25                     continue;
     26                 }
     27                 FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
     28                 if (currentFieldName == null) {
     29                     // We're parsing the outer multipart
     30                     String fieldName = getFieldName(headers);
     31                     if (fieldName != null) {
     32                         String subContentType = headers.getHeader(CONTENT_TYPE);
     33                         if (subContentType != null
     34                                 &&  subContentType.toLowerCase(Locale.ENGLISH)
     35                                         .startsWith(MULTIPART_MIXED)) {
     36                             currentFieldName = fieldName;
     37                             // Multiple files associated with this field name
     38                             byte[] subBoundary = getBoundary(subContentType);
     39                             multi.setBoundary(subBoundary);
     40                             skipPreamble = true;
     41                             continue;
     42                         }
     43                         String fileName = getFileName(headers);
     44                         currentItem = new FileItemStreamImpl(fileName,
     45                                 fieldName, headers.getHeader(CONTENT_TYPE),
     46                                 fileName == null, getContentLength(headers));
     47                         currentItem.setHeaders(headers);
     48                         notifier.noteItem();
     49                         itemValid = true;
     50                         return true;
     51                     }
     52                 } else {
     53                     String fileName = getFileName(headers);
     54                     if (fileName != null) {
     55                         currentItem = new FileItemStreamImpl(fileName,
     56                                 currentFieldName,
     57                                 headers.getHeader(CONTENT_TYPE),
     58                                 false, getContentLength(headers));
     59                         currentItem.setHeaders(headers);
     60                         notifier.noteItem();
     61                         itemValid = true;
     62                         return true;
     63                     }
     64                 }
     65                 multi.discardBodyData();
     66             }
     67         }
     68 
     69         private long getContentLength(FileItemHeaders pHeaders) {
     70             try {
     71                 return Long.parseLong(pHeaders.getHeader(CONTENT_LENGTH));
     72             } catch (Exception e) {
     73                 return -1;
     74             }
     75         }
     76 
     77         /**
     78          * Returns, whether another instance of {@link FileItemStream}
     79          * is available.
     80          *
     81          * @throws FileUploadException Parsing or processing the
     82          *   file item failed.
     83          * @throws IOException Reading the file item failed.
     84          * @return True, if one or more additional file items
     85          *   are available, otherwise false.
     86          */
     87         public boolean hasNext() throws FileUploadException, IOException {
     88             if (eof) {
     89                 return false;
     90             }
     91             if (itemValid) {
     92                 return true;
     93             }
     94             try {
     95                 return findNextItem();
     96             } catch (FileUploadIOException e) {
     97                 // unwrap encapsulated SizeException
     98                 throw (FileUploadException) e.getCause();
     99             }
    100         }
    101 
    102         /**
    103          * Returns the next available {@link FileItemStream}.
    104          *
    105          * @throws java.util.NoSuchElementException No more items are
    106          *   available. Use {@link #hasNext()} to prevent this exception.
    107          * @throws FileUploadException Parsing or processing the
    108          *   file item failed.
    109          * @throws IOException Reading the file item failed.
    110          * @return FileItemStream instance, which provides
    111          *   access to the next file item.
    112          */
    113         public FileItemStream next() throws FileUploadException, IOException {
    114             if (eof  ||  (!itemValid && !hasNext())) {
    115                 throw new NoSuchElementException();
    116             }
    117             itemValid = false;
    118             return currentItem;
    119         }
    View Code
  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/act262/p/Java.html
Copyright © 2011-2022 走看看