分享

文件上传自写代码实现servlet3.0,part

 hh3755 2011-08-09
原文: http://wese345./blog/686108最近几天在做文件上传的时候,使用enctype="multipart/form-data"时,在spring的controller里面没有像struts那样的Formfile之类封装好的类,可以直接拿到此类form里面的值。也许你会说用第三方jar来解决呀,是啊,像commons-fileupload.jar,SmartUpload我用过,确实好用啊,可是,这样就算完了?怎么实现的? 我不用它自己写不行吗?不就是个文件上传嘛! 
    在网上查了下,才知道浏览器Post的过来到controller的不像平时普通提交表单时用getParameter()方法就能拿到,而是一个流ServletInputStream。通过firebug可以清楚的看到post的数据格式: 
     --(随即生成数字或字母) 
    Content-Disposition: form-data; name="title" 
    (回车) 
    值 
    --(随即生成数字或字母) 
    Content-Disposition: form-data; name="1.txt"; filename="C:\1.txt" 
    Content-Type: text/plain 
    回车 
     文件内容 
    --(随即生成数字或字母)-- 
    回车 

     这不就行了,既然知道了流的格式,自己构造数组来存入流数据不就行了。
Java代码  收藏代码
  1. //我定义的数组m_binArray  
  2. this.m_totalBytes = this.m_request.getContentLength();  
  3. this.m_binArray = new byte[this.m_totalBytes];  
  4.   
  5. ServletInputStream sis = this.m_request.getInputStream();  
  6. int i=0;  
  7. int j=0;  
  8. for (; i < this.m_totalBytes; i += j)  
  9. {  
  10.   try {  
  11.     /* 尝试将流写入数组:从数组的i索引开始,并读取一定长度的流,该长度可能会比计划长度小 
  12.      * 返回实际读取的字节数。有人说用readline效率会高,我没试也不便评论 
  13.      */  
  14.     j = sis.read(this.m_binArray, i, this.m_totalBytes-i);  
  15.       
  16.   
  17.     System.out.println(new String(this.m_binArray,i,j));  
  18.   
  19.   }  
  20.   catch (Exception exception)  
  21.   {  
  22.     e.printStackTrace();  
  23.   }  
  24. }  

    
    这样你可以在控制台上看到如上我说的那种格式数据,下面就可以自己解析了。附件代码是我项目中用到的上传类。 
    这是我第一次发博,以前只是看,“拿”,现在也贡献一下,呵呵。

在 Servlet 3.0 中处理 multipart/form-data 请求的两个辅助方法Two Assistant Methods for Dealing with multipart/form-data Request in Servlet 3.0
Servlet 3.0 引入了 javax.servlet.http.Part 接口,从而提供了对multipart/form-data 类型的 HTTP 请求的直接支持,我们从此就可以摆脱诸如 Apache Commons FileUpload 之类的第三方依赖。然而,该支持太过单纯,所以还要多做点事情,以便能更有效地进行工作。我将在本文中介绍两个辅助方法。Servlet 3.0 comes with out-of-the-box support for handling HTTP request of type multipart/form-data by introducing of javax.servlet.http .Part interface, freeing us from 3rd party dependencies such as Apache Commons FileUpload. However, the support so pure that we still need to do a little more work to get us work more effective. I'll demostrate two assistant methods in this article.
首先,Servlet 3.0 没有提供方法将 Part 对象专为字符串。multipart/form-data 请求也可能包含字符串参数。在这种情况下,我们可以写一个工具方法来从 Part 对象读取字节,然后将其解析为字符串。为了方便,还可以让这个方法能处理最常见的application/x-www-form-urlencoded 请求:First, there's no method to translate a Part object to a string value in Servlet 3.0. A multipart/form-datarequest may also contain string parameters. In this case, we can wrtie a utility method to read bytes from thePart object and parse them to a string value. For convenience we also enable the method to handle the most common application/x-www-form-urlencoded request:
  1. /**
  2.  * Returns the value of a request parameter from the given {@code HttpServletRequest}
  3.  * as a {@code String}, or {@code null} if the parameter does not exist.
  4.  * This method can handle request of type both {@code application/x-www-form-urlencoded}
  5.  * and {@code multipart/form-data}.
  6.  * @param req The request object.
  7.  * @param name The name of the parameter.
  8.  * @param charset The name of charset for parsing bytes to string if the request
  9.  * if of type {@code multipart/form-data}. An improper charset might lead to
  10.  * messy code in the returned string.
  11.  * @return The velue of the parameter.
  12.  */
  13. public static String getParameter(HttpServletRequest req, String name,String charse) {
  14.     // First assume the request is of type application/x-www-form-urlencoded.
  15.     String value = req.getParameter(name);
  16.     if (value != null) {
  17.         return value;
  18.     }
  19.     // Trying to handle the request as a multipart/form-data type.
  20.     try {
  21.         Reader in = new InputStreamReader(part.getInputStream(), charset);
  22.         StringBuilder sb = new StringBuilder();
  23.         char[] buffer = new char[256];
  24.         int read = 0;
  25.         while ((read = in.read(buffer)) != -1) {
  26.             sb.append(buffer, 0, read);
  27.         }
  28.         in.close();
  29.         return sb.toString();
  30.     } catch (Exception ex) {
  31.         return null;
  32.     }
  33. }
类似地,可以写一个 getParameterValues 方法去处理名称相同的多个参数,所以就不在这里列出代码了。第二个辅助方法用于从 Part 对象获取文件名。Part 接口并没有提供这种方法,但我们可以容易地从头部提取出文件名:In the similar manner we can write a getParameterValues method to handle multiple parameter with the same name, so I'm not going to list the code here. The sencond assistant method is for getting the filename from a Part object. The Part interface doesn't provide such a method, but we can easily extract the filename from the header:
  1. private static final String FILENAME_KEY = "filename=\"";
  2. /**
  3.  * Gets the original filename of a {@code Part}. The filename is encoded in
  4.  * the {@code content-disposition} header of the {@code Part} as the value
  5.  * of {@code filename} parameter.
  6.  * @param part The {@code Part} object.
  7.  * @return The filename of the part, or {@code null} if the part doesn't
  8.  * contain a file.
  9.  */
  10. public static String getFileNameFromPart(Part part) {
  11.     String cdHeader = part.getHeader("content-disposition");
  12.     if (cdHeader == null) {
  13.         return null;
  14.     }
  15.     for (String s : cdHeader.split("; ")) {
  16.         if (s.startsWith(FILENAME_KEY)) {
  17.             // Some stupid browers, e.g. IE, put the full file path on the
  18.             // client machine as the value, so we have to extract the filename
  19.             // out from it.
  20.             String path = s.substring(FILENAME_KEY.length(),
  21.                     s.length() - 1).replaceAll("\\\\", "/");
  22.             return path.substring(path.lastIndexOf("/") + 1);
  23.         }
  24.     }
  25.     return null;
  26. }
http://www.oschina.net/code/snippet_93779_3286
代码实现:

[代码] Servlet 3.0 实现文件上传

01import javax.servlet.ServletException;
02import javax.servlet.annotation.MultipartConfig;
03import javax.servlet.annotation.WebServlet;
04import javax.servlet.http.HttpServletRequest;
05import javax.servlet.http.HttpServletResponse;
06import javax.servlet.http.Part;
07import java.io.File;
08import java.io.IOException;
09 
10@WebServlet(name = "FileUploadServlet", urlPatterns = {"/upload"})
11@MultipartConfig(location = "D:\\", fileSizeThreshold = 1024)
12public class FileUploadServlet extends javax.servlet.http.HttpServlet {
13 
14    private static final String SAVE_PATH = "D:\\";
15 
16    public void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
17 
18        request.setCharacterEncoding("utf-8");
19 
20        Part part = request.getPart("file"); //  request.getParts();
21        File f = new File(SAVE_PATH + File.separator);
22        if (!f.exists()) {
23            f.mkdirs();
24        }
25 
26        String h = part.getHeader("content-disposition");
27        String filename = h.substring(h.lastIndexOf("=") + 2, h.length() - 1);
28 
29        part.write(SAVE_PATH + File.separator + filename);
30    }
31}

[代码] [HTML]代码

01<%@ page contentType="text/html;charset=UTF-8" language="java" %>
02<html>
03<head><title>Servlet 3.0 File Upload</title></head>
04<body>
05 
06<form action="/upload" method="post" enctype="multipart/form-data">
07    <input type="file" name="file"/>
08    <button type="submit">submit</button>
09</form>
10 
11</body>
12</html>

另有对servlet3.0新特性的详解:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多