jboss web - JSF和Servlet上传文件汇总 - chinse version

Version 1

    原文:http://javaarm.com/faces/display.xhtml?tid=3109&page=1

    英文版:https://community.jboss.org/wiki/JbossWeb-UploadWithJSFAndServlet-EnglishVersion (I will translate it into english ASAP.)

     

    JSF和Servlet上传文件汇总

     

    本作者在开发http://javaarm.com个人网站的上传功能时,遇到了不少问题,有些是概念没有搞清楚,在经历一番探索之后,所有技术问题都解决。本文汇总了用JSF或Servlet上传文件的各种组合。期望本文对大家有用。

     

    参考

    http://docs.oracle.com/javaee/6/tutorial/doc/glrbb.html

    Chapter 16 Uploading Files with Java Servlet Technology

    Supporting file uploads is a very basic and common requirement for many web applications. Prior to Servlet 3.0, implementing file upload required the use of external libraries or complex input processing. Version 3.0 of the Java Servlet specification helps to provide a viable solution to the problem in a generic and portable way. The Servlet 3.0 specification supports file upload out of the box, so any web container that implements the specification can parse multipart requests and make mime attachments available through the HttpServletRequest object.

    A new annotation, javax.servlet.annotation.MultipartConfig, is used to indicate that the servlet on which it is declared expects requests to made using the multipart/form-data MIME type. Servlets that are annotated with @MultipartConfig can retrieve the Part components of a given multipart/form-data request by calling the request.getPart(String name) or request.getParts() method.

    The following topics are addressed here:

     

     

     

    总体注意事项:

    (1) 我们必须把用于上传目的的常规的HTML元素<form />元素的method 属性设置为 "post",并且把 enctype 属性设置为 "multipart/form-data"。比如:<form method="post" action="UploadServlet" enctype="multipart/form-data" >。

     

    (2) 关于<form />元素的action属性

    假设

    • 我们的web应用程序为ybxiang-forum-war,在JBoss AS 7中的部署目录为${JBOSS_HOME}\standalone\deployments\ybxiang-forum.ear\ybxiang-forum-war.war。
    • 上 传页面(可以是JSF, JSP, HTML, XHTML)为upload.jsp,位于${JBOSS_HOME}\standalone\deployments\ybxiang- forum.ear\ybxiang-forum-war.war\upload目录之下。

    那么

    • 如果 upload.jsp包含的<form />为<form method="post" action="UploadServlet" enctype="multipart/form-data" >,那么,action="UploadServlet"实际会被解析为action="http://domain-name/upload /UploadServlet",而不是action="http://domain-name/UploadServlet"!这种情况下,实际的 UploadServlet.java要映到“/upload/UploadServlet”,比如我们可以用注解映射:@WebServlet(" /upload/UploadServlet")。不推荐!
    • 如果upload.jsp包含的<form />为<form method="post" action="/UploadServlet" enctype="multipart/form-data" >(注意:“UploadServlet”前面有个斜杠"/"),那 么,action="UploadServlet"实际会被解析为action="http://domain-name /UploadServlet",而不是action="http://domain-name/upload/UploadServlet"!这种情况 下,实际的 UploadServlet.java要映到“/UploadServlet”,比如我们可以用注解映射:@WebServlet(" /UploadServlet")。推荐!

     

     

     

    1. HTML/JSF/JSP 页面 + <form /> + Upload Servlet

    HTML/JSF/JSP页面中,使用标准HTML元素<form />上传文件是可行的。

     

    1.1 HTML/JSF/JSP页面

    <form method="post" action="/UploadServlet" enctype="multipart/form-data" >
        Directory:  <input type="text" name="targetDirectory" value="/home/ybxiang/file/" size="60" /><br />
        File:<input type="file" name="file1" id="file1" /> <br/>
        File:<input type="file" name="file2" id="file2" /> <br/>
        <input type="submit" value="Upload" name="upload" id="upload" />
    </form>

    注意:“UploadServlet”前面有额斜杠“/”。

    1.2 UploadServlet.java

    我们只给出大致代码框架,下面 链接 我们会详细描述它。注意@WebServlet("/UploadServlet")这个注解中,“UploadServlet”前面有额斜杠“/”。

    @WebServlet("/UploadServlet")

    public class UploadServlet_CalledByJSF extends HttpServlet {

        private static final long serialVersionUID = 1L;

        protected void doPost(HttpServletRequest request,

                HttpServletResponse response) throws ServletException, IOException {

            response.setContentType("text/html;charset=UTF-8");

            ...

        }

    }

     

     

     

    2. JSF 页面 + <h:form /> + Upload Servlet

    <h:form />元素 没有 <form />元素所具有的 method和action属性:

        (a) 其method属性总是"post"

        (b) 其action属性由该<h:form />元素之内的<h:commandButton />决定

    因此,无法让<h:form />去调用某个Upload Servlet!

     

    因此下面的做法是无法上传的。

     

    2.1 JSF页面

    <h:form method="post" action="/UploadServlet" enctype="multipart/form-data">
        File:
        <input type="file" name="file" id="file" /> <br/>
        Destination:
        <input type="text" value="/tmp" name="destination"/>
        <br />
        <input type="submit" value="Upload" name="upload" id="upload" />
    </h:form>

    我们强制为<h:form>设置属性:method="post" action="/UploadServlet"。但是该<h:form> 实际会被解析为:

    <form id="j_idt122" name="j_idt122" method="post" action="/faces/system/upload-bad.xhtml" enctype="multipart/form-data">
    <input name="j_idt122" value="j_idt122" type="hidden">

     

    action无法指向我们期望的 "/UploadServlet"。所以是不可行的!

     

     

     

    3. JSF 页面 + <h:inputFile /> +JSF MBean (没有测试过!)

    JSF2.2新增了 <h:inputFile />标签,我们可以直接用JSF MBean来上传文件。

    3.1 JSF页面

    <h:form enctype="multipart/form-data">

        <h:inputFile id="file"  value="#{fileUploadMBean.file1}"/><br />

        <h:commandButton id="button" action="#{fileUploadMBean.upload()}" value="Upload"/>

    </h:form>

     

     

     

    3.2 JSF MBean - FileUploadMBean.java

    import javax.faces.bean.ManagedBean;

    import javax.faces.bean.RequestScoped;

    import javax.servlet.http.Part;

     

    import com.ybxiang.forum.jsfmbean.Constants;

    import com.ybxiang.forum.jsfmbean.JSFHelper;

     

    /**

    * 注意:JSF从2.2版本才开始支持 <h:inputFile />

    *

    * JSF页面:

    *         <h:form enctype="multipart/form-data">

    *             <h:inputFile id="file1"  value="#{fileUploadMBean.file1}"/><br />

    *             <h:inputFile id="file2"  value="#{fileUploadMBean.file2}"/><br />

    *             <h:inputFile id="file3"  value="#{fileUploadMBean.file3}"/><br />

    *             <h:inputFile id="file4"  value="#{fileUploadMBean.file4}"/><br />

    *             <h:inputFile id="file5"  value="#{fileUploadMBean.file5}"/><br />

    *             <h:commandButton id="button" action="#{fileUploadMBean.upload()}" value="Upload"/>

    *         </h:form>

    *

    * 将javax.servlet.http.Part写入磁盘的代码可以参考:

    * (a) http://docs.oracle.com/javaee/6/tutorial/doc/glrbb.html

    * (b) http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html

    */

    @ManagedBean

    @RequestScoped

    public class FileUploadMBean {

        private Part file1;

        private Part file2;

        private Part file3;

        private Part file4;

        private Part file5;

       

        public Part getFile1() {

            return file1;

        }

        public void setFile1(Part file1) {

            this.file1 = file1;

        }

     

        public Part getFile2() {

            return file2;

        }

        public void setFile2(Part file2) {

            this.file2 = file2;

        }

     

        public Part getFile3() {

            return file3;

        }

        public void setFile3(Part file3) {

            this.file3 = file3;

        }

     

        public Part getFile4() {

            return file4;

        }

        public void setFile4(Part file4) {

            this.file4 = file4;

        }

     

        public Part getFile5() {

            return file5;

        }

        public void setFile5(Part file5) {

            this.file5 = file5;

        }

     

     

     

    3.2 JSF MBean - FileUploadMBean.java

     

    import javax.faces.bean.ManagedBean;

    import javax.faces.bean.RequestScoped;

    import javax.servlet.http.Part;

     

    import com.ybxiang.forum.jsfmbean.Constants;

    import com.ybxiang.forum.jsfmbean.JSFHelper;

     

    /**

    * 参见:http://javaarm.com/faces/display.xhtml?tid=3109

    *

    * 注意:JSF从2.2版本才开始支持 <h:inputFile />

    * 将javax.servlet.http.Part写入磁盘的代码可以参考:

    * (a) http://docs.oracle.com/javaee/6/tutorial/doc/glrbb.html

    * (b) http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html

    */

    @ManagedBean

    @RequestScoped

    public class FileUploadMBean {

        private Part file1;

        private Part file2;

        private Part file3;

        private Part file4;

        private Part file5;

       

        public Part getFile1() {

            return file1;

        }

        public void setFile1(Part file1) {

            this.file1 = file1;

        }

     

        public Part getFile2() {

            return file2;

        }

        public void setFile2(Part file2) {

            this.file2 = file2;

        }

     

        public Part getFile3() {

            return file3;

        }

        public void setFile3(Part file3) {

            this.file3 = file3;

        }

     

        public Part getFile4() {

            return file4;

        }

        public void setFile4(Part file4) {

            this.file4 = file4;

        }

     

        public Part getFile5() {

            return file5;

        }

        public void setFile5(Part file5) {

            this.file5 = file5;

        }

     

     

        public String upload(){

            boolean jsf22Supported = false;

            if(! jsf22Supported){

                String errMsg = "当前JBoss AS不支持JSF2.2(JSF从2.2版本才开始支持 <h:inputFile />)!";

                JSFHelper.addErrorMessage(errMsg);

                return Constants.RETURN_FAILURE;

            }

            //TODO: 权限控制

            //TODO: 文件大小控制

            //TODO: 图像宽度控制

           

            String file1_name = getFileName(getFile1());

            String file2_name = getFileName(getFile2());

            String file3_name = getFileName(getFile3());

            String file4_name = getFileName(getFile4());

            String file5_name = getFileName(getFile5());

            try{

                getFile1().write("d://upload"+file1_name);

                getFile2().write("d://upload"+file2_name);

                getFile3().write("d://upload"+file3_name);

                getFile4().write("d://upload"+file4_name);

                getFile5().write("d://upload"+file5_name);

            }catch(Exception e){

                String errMsg = e.getMessage();

                JSFHelper.addErrorMessage(errMsg);

                return Constants.RETURN_FAILURE;

            }

     

            return Constants.RETURN_SUCCESS;

        }

       

        private String getFileName(final Part part) {

            for (String content : part.getHeader("content-disposition").split(";")) {

                if (content.trim().startsWith("filename")) {

                    return content.substring(content.indexOf('=') + 1).trim()

                            .replace("\"", "");

                }

            }

            return null;

        }

    }

     

    5 详述UploadServlet.java

    关于 javax.servlet.annotation.MultipartConfig 注解

    @java.lang.annotation.Target(value={java.lang.annotation.ElementType.TYPE})
    @java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
    public abstract @interface javax.servlet.annotation.MultipartConfig extends java.lang.annotation.Annotation {
      public abstract java.lang.String location() default "";
      public abstract long maxFileSize() default -1L;
      public abstract long maxRequestSize() default -1L;
      public abstract int fileSizeThreshold() default (int) 0;
    }

    参见1:http://docs.oracle.com/javaee/6/tutorial/doc/glrbb.html

    *************************************************************************************************

    A new annotation, javax.servlet.annotation.MultipartConfig, is used to indicate that the servlet on which it is declared expects requests to made using the multipart/form-data MIME type. Servlets that are annotated with @MultipartConfig can retrieve the Part components of a given multipart/form-data request by calling the request.getPart(String name) or request.getParts() method.

    *************************************************************************************************

     

    参见2:http://docs.oracle.com/javaee/6/tutorial/doc/gmhal.html

    *************************************************************************************************

    The @MultipartConfig Annotation

    The @MultipartConfig annotation supports the following optional attributes:

    • location: An absolute path to a directory on the file system. The location attribute does not support a path relative to the application context. This location is used to store files temporarily while the parts are processed or when the size of the file exceeds the specified fileSizeThreshold setting. The default location is ""
    • fileSizeThreshold: The file size in bytes after which the file will be temporarily stored on disk. The default size is 0 bytes. 
    • MaxFileSize: The maximum size allowed for uploaded files, in bytes. If the size of any uploaded file is greater than this size, the web container will throw an exception (IllegalStateException). The default size is unlimited. 
    • maxRequestSize: The maximum size allowed for a multipart/form-data request, in bytes. The web container will throw an exception if the overall size of all uploaded files exceeds this threshold. The default size is unlimited. 

    For, example, the @MultipartConfig annotation could be constructed as follows:

    @MultipartConfig(location="/tmp", fileSizeThreshold=1024*1024, maxFileSize=1024*1024*5, maxRequestSize=1024*1024*5*5)

    Instead of using the @MultipartConfig annotation to hard-code these attributes in your file upload servlet, you could add the following as a child element of the servlet configuration element in the web.xml file.

    <multipart-config> <location>/tmp</location> <max-file-size>20848820</max-file-size> <max-request-size>418018841</max-request-size> <file-size-threshold>1048576</file-size-threshold> </multipart-config>

    注意:我们可以在web.xml中,为某个Servlet定义MultipartConfig。其效果与 在该Servlet的class上使用 @MultipartConfig 注解一样。

    *************************************************************************************************

     

    5.1 UploadServlet.java - 不带 @MultipartConfig

    如果我们为 UploadServlet.java 声明注解@MultipartConfig(...),那么html form中的所有fields(包括<input type='text' ... />, <input type='file' .. />...)都将被封装进 javax.servlet.http.Part;而Servlet容器会 把参数信息从 javax.servlet.http.Part里面解析出来,放入UploadServlet的HttpServletRequest中;这样 request.getParameterMap()就不包含任何元素!所以 request.getParameter(ONE_FILED_NAME)总是为null!

     

    但是,我们可以利用 Apache的 commons-fileupload-1.2.2.jar和commons-io-2.3.jar来从request中读取这些 javax.servlet.http.Part,并解析出所有field(包括<input type='text' ... />, <input type='file' .. />...)的信息!

     

    (a) UploadServlet_WithoutMultipartConfig.java

     

    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Iterator;
    import java.util.List;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;

    /**
    * 参考: http://javaarm.com/faces/display.xhtml?tid=2190
    */
    @WebServlet("/UploadServlet")
    public class UploadServlet_WithoutMultipartConfig extends HttpServlet {
        private static final long serialVersionUID = 1L;
       
        public static final int DEFAULT_UPLOAD_maxFileSize = 5242880;
        public static final int DEFAULT_UPLOAD_maxRequestSize = 418018841;
        public static final int DEFAULT_UPLOAD_fileSizeThreshold = 1048576;
       
        public static final String FILED_NAME_targetDirectory = "targetDirectory";
       
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=UTF-8");
           
            String targetDirectory = request.getParameter(FILED_NAME_targetDirectory);
            if(targetDirectory==null){
                System.out.println("This is normal:");
                System.out.println("If we do NOT declare @MultipartConfig() on UploadServlet, ");
                System.out.println("all fileds(<input type='text' ... />, <input type='file' .. />) in html from is wrapped in javax.servlet.http.Part, ");
                System.out.println("so, request.getParameterMap() contains nothing!");
            }else{
                System.out.println("IMPOSSIBLE!");
            }
                   
            if (!ServletFileUpload.isMultipartContent(request)) {
                printFeedBackInfo(response,"Request中没有上传文件!请确保<form>的enctyp为'multipart/form-data'!");
                return;
            }
           
            //File targetDirectoryFile = new File(targetDirectory);
            //if(! targetDirectoryFile.exists()){
            //    targetDirectoryFile.mkdirs();
            //}

     

            DiskFileItemFactory factory = new DiskFileItemFactory();

            factory.setSizeThreshold(DEFAULT_UPLOAD_fileSizeThreshold);

            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

           

            ServletFileUpload upload = new ServletFileUpload(factory);

            upload.setFileSizeMax(DEFAULT_UPLOAD_maxFileSize);

            upload.setSizeMax(DEFAULT_UPLOAD_maxRequestSize);

           

            StringBuilder sb_success = new StringBuilder("上传成功的文件:<br/>");

            StringBuilder sb_failure = new StringBuilder("上传失败的文件:<br/>");

            try {

                @SuppressWarnings("unchecked")

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

               

                targetDirectory = getParameter(list, FILED_NAME_targetDirectory);

                if(targetDirectory==null){

                    printFeedBackInfo(response,"IMPOSSIBLE: targetDirectory is null.");

                    return;

                }

                File targetDirectoryFile = new File(targetDirectory);

                if(! targetDirectoryFile.exists()){

                    targetDirectoryFile.mkdirs();

                }

               

                Iterator<FileItem> it = list.iterator();

                while (it.hasNext()) {

                    FileItem item = it.next();

                    if (!item.isFormField()) {

                        String fileName = new File(item.getName()).getName();

                        if(fileName==null||fileName.trim().length()==0){

                            //<input type="file" name="file_i" size="60" /> is NOT selected.

                        }else{

                            item.write(new File(targetDirectory,fileName));

                            sb_success.append(fileName).append("<br />");

                        }

                    }

                }

            } catch (Exception ex) {

                printFeedBackInfo(response,"错误:"+ex.getMessage());

                return;

            }

     

            StringBuilder sb_result = new StringBuilder("上传结果:<br />");

            sb_result.append("(a) ").append(sb_success.toString()).append("<br/>");

            sb_result.append("(b) ").append(sb_failure.toString());

            printFeedBackInfo(response,sb_result.toString());

        }

     

     

        private String getParameter(List<FileItem>list,String parameterName){

            Iterator<FileItem> it = list.iterator();

            while (it.hasNext()) {

                FileItem item = it.next();

                if (!item.isFormField()) {

                    //Ignore File Item!

                }else{

                    if(item.getFieldName().equals(parameterName)){

                        return item.getString();

                    }

                }

            }

            return null;

        }

     

        private void printFeedBackInfo(HttpServletResponse response,String info) throws IOException{

            PrintWriter writer = response.getWriter();

            writer.println(info);

            writer.flush();

        }

    }

     

    (b) html form

    <form method="post" action="/UploadServlet" enctype="multipart/form-data" >

        Directory:  <input type="text" name="targetDirectory" value="/home/ybxiang/file/" size="60" /><br />

        File:<input type="file" name="file1" id="file1" /> <br/>

        File:<input type="file" name="file2" id="file2" /> <br/>

        <input type="submit" value="Upload" name="upload" id="upload" />

    </form>

     

     

     

    5.2 UploadServlet.java - 带 @MultipartConfig

    如果我们为 UploadServlet.java 声明注解@MultipartConfig(...),那么html form中的所有fields(包括<input type='text' ... />, <input type='file' .. />...)都将被封装进 javax.servlet.http.Part;而Servlet容器会把参数信息从 javax.servlet.http.Part里面解析出来,放入UploadServlet的HttpServletRequest中;这样 request.getParameterMap()就包含了我们期望的参数的信息!

     

    在这个情况下,Apache的 commons-fileupload-1.2.2.jar和commons-io-2.3.jar从request中读取这些 javax.servlet.http.Part 就会有问题:为空!我们可以直接从 javax.servlet.http.Part里面读取文件,参见:http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html

     

    @MultipartConfig的下面几种表达方式都是等价的:

    • 不带参数
    @MultipartConfig
    • 带默认的参数
    @MultipartConfig(
            location="",
            fileSizeThreshold = 0,
            maxFileSize = -1,
            maxRequestSize = -1)
    • 最大限度的参数
    @MultipartConfig(
            location="",
            fileSizeThreshold = Integer.MAX_VALUE,
            maxFileSize = Long.MAX_VALUE,
            maxRequestSize = Long.MAX_VALUE)

    注意:

    • 如 果我们把maxFileSize设成2M,而我们上传的文件是5M,那么HttpServletRequest中所有fields(包 括<input type='text' ... />, <input type='file' .. />)都被忽略!
    • 如果我们把maxRequestSize设成10M,而我们一次性上传的2个文件文件都是7M,那么HttpServletRequest中所有fields(包 括<input type='text' ... />, <input type='file' .. />)都被忽略!

     

     

    5.2.1 用commons-fileupload-1.2.2.jar 和commons-io-2.3.jar提取文件 失败

    (a) UploadServlet_WithoutMultipartConfig.java

     

    和UploadServlet_WithoutMultipartConfig,java非常接近!

     

    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Iterator;
    import java.util.List;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;

    /**
    * 参考:http://javaarm.com/faces/display.xhtml?tid=3109&page=1#post_38375
    */
    @WebServlet("/UploadServlet_demo2")
    @MultipartConfig(
            location="",
            fileSizeThreshold = 1024 * 1024 * 2,
            maxFileSize = 1024 * 1024 * 8,
            maxRequestSize = 1024 * 1024 * 10)

    public class UploadServlet_WithMultipartConfig extends HttpServlet {
        private static final long serialVersionUID = 1L;
       
        public static final int DEFAULT_UPLOAD_maxFileSize = 5242880;
        public static final int DEFAULT_UPLOAD_maxRequestSize = 418018841;
        public static final int DEFAULT_UPLOAD_fileSizeThreshold = 1048576;
       
        public static final String FILED_NAME_targetDirectory = "targetDirectory";
       
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=UTF-8");
           
            if(!ServletHelper.isCurrentUserAdministrator(request)){
                printFeedBackInfo(response,"这是测试程序,只允许管理员调用");
                return;
            }
           
            String targetDirectory = request.getParameter(FILED_NAME_targetDirectory);
            if(targetDirectory!=null){
                System.out.println("正常情况:");
                System.out.println("If we do declare @MultipartConfig() on UploadServlet, ");
                System.out.println("  all fileds(<input type='text' ... />, <input type='file' .. />) in html from is wrapped into javax.servlet.http.Part,");
                System.out.println("  but they will be unwrapped and injected into this servlet's request, ");
                System.out.println("  so, request.getParameterMap() contains unwrapped fields!");
                System.out.println("(1) We can get parameter by request.getParameter(xxx)");
                System.out.println("(2) Bellow org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(HttpServletRequest) returns empty List!");
            }else{
                printFeedBackInfo(response,"上传文件太大,导致request中所有fields(包括<input type='text' ... />, <input type='file' .. />)都被忽略!");
                return;
            }

            if (!ServletFileUpload.isMultipartContent(request)) {
                printFeedBackInfo(response,"Request中没有上传文件!请确保<form>的enctyp为'multipart/form-data'!");
                return;
            }

     

     

     

            DiskFileItemFactory factory = new DiskFileItemFactory();

            factory.setSizeThreshold(DEFAULT_UPLOAD_fileSizeThreshold);

            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

           

            ServletFileUpload upload = new ServletFileUpload(factory);

            upload.setFileSizeMax(DEFAULT_UPLOAD_maxFileSize);

            upload.setSizeMax(DEFAULT_UPLOAD_maxRequestSize);

           

            StringBuilder sb_success = new StringBuilder("上传成功的文件:<br/>");

            StringBuilder sb_failure = new StringBuilder("上传失败的文件:<br/>");

            try {

                @SuppressWarnings("unchecked")

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

               

                if(getParameter(list, FILED_NAME_targetDirectory)!=null){

                    printFeedBackInfo(response,"IMPOSSIBLE: targetDirectory should be null.");

                    return;

                }

               

                if(list==null||list.size()==0){

                    printFeedBackInfo(response,"正常结果:@MultipartConfig声明到该Servlet之上,会导致该 Servlet将上传的javax.servlet.http.Part对象解封并插入HttpServletRequest中,");
                    printFeedBackInfo(response,"      从而导致 org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(HttpServletRequest) 无法从HttpServletRequest中提取到javax.servlet.http.Part对象,因此返回空的List");

                    return;

                }

                //下面的代码不会被执行到

                File targetDirectoryFile = new File(targetDirectory);

                if(! targetDirectoryFile.exists()){

                    targetDirectoryFile.mkdirs();

                }

               

                Iterator<FileItem> it = list.iterator();

                while (it.hasNext()) {

                    FileItem item = it.next();

                    if (!item.isFormField()) {

                        String fileName = new File(item.getName()).getName();

                        if(fileName==null||fileName.trim().length()==0){

                            //<input type="file" name="file_i" size="60" /> is NOT selected.

                        }else{

                            item.write(new File(targetDirectory,fileName));

                            sb_success.append(fileName).append("<br />");

                        }

                    }

                }

            } catch (Exception ex) {

                printFeedBackInfo(response,"错误:"+ex.getMessage());

                return;

            }

            StringBuilder sb_result = new StringBuilder("上传结果:<br />");
            sb_result.append("(a) ").append(sb_success.toString()).append("<br/>");
            sb_result.append("(b) ").append(sb_failure.toString());
            printFeedBackInfo(response,sb_result.toString());
        }

     

     

        private String getParameter(List<FileItem>list,String parameterName){

            Iterator<FileItem> it = list.iterator();

            while (it.hasNext()) {

                FileItem item = it.next();

                if (!item.isFormField()) {

                    //Ignore File Item!

                }else{

                    if(item.getFieldName().equals(parameterName)){

                        return item.getString();

                    }

                }

            }

            return null;

        }

        private void printFeedBackInfo(HttpServletResponse response,String info) throws IOException{

            PrintWriter writer = response.getWriter();

            writer.println(info);

            writer.flush();

        }

    }

     

     

     

    (b) html form
    <form method="post" action="/UploadServlet_demo2" enctype="multipart/form-data" >

        Directory:  <input type="text" name="targetDirectory" value="/home/ybxiang/file/" size="60" /><br />

        File:<input type="file" name="file1" id="file1" /> <br/>

        File:<input type="file" name="file2" id="file2" /> <br/>

        <input type="submit" value="Upload" name="upload" id="upload" />

    </form>

     

     

     

    5.2.2 用直接用javax.servlet.http.HttpServletRequest.getPart(String)提取文件 - 成功

    本例参考:http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html

     

    (a) UploadServlet_WithMultipartConfig_SunExample.java

     

    import java.io.*;

    import java.util.logging.Level;

    import java.util.logging.Logger;

     

    import javax.servlet.ServletException;

    import javax.servlet.annotation.MultipartConfig;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import javax.servlet.http.Part;

     

    /**

    * 测试通过!

    *

    * http://docs.oracle.com/javaee/6/tutorial/doc/glraq.html

    * 注意:上传文件大小无任何限制!

    */

    @WebServlet("/UploadServlet_demo3")

    @MultipartConfig

    public class UploadServlet_WithMultipartConfig_SunExample extends HttpServlet {

        private static final long serialVersionUID = 1L;

       

        private final static Logger LOGGER =

                Logger.getLogger(UploadServlet_WithMultipartConfig_SunExample.class.getCanonicalName());

       

        public static final String FILED_NAME_targetDirectory = "targetDirectory";

        public static final String FILED_NAME_file1 = "file1";

        //public static final String FILED_NAME_file2 = "file2";

       

        protected void doPost(HttpServletRequest request,

                HttpServletResponse response) throws ServletException, IOException {

            processRequest(request,response);

        }

     

     

        protected void processRequest(HttpServletRequest request,

                HttpServletResponse response)

                throws ServletException, IOException {

            response.setContentType("text/html;charset=UTF-8");

           

            if(!ServletHelper.isCurrentUserAdministrator(request)){

                printFeedBackInfo(response,"这是测试程序,只允许管理员调用");

                return;

            }

     

            // Create path components to save the file

            final String path = request.getParameter(FILED_NAME_targetDirectory);

            if(path!=null){

                //NORMAL

            }else{

                //FILE is too large!

            }

            File targetDirectoryFile = new File(path);

            if(! targetDirectoryFile.exists()){

                targetDirectoryFile.mkdirs();

            }

           

            final Part filePart = request.getPart(FILED_NAME_file1);

            final String fileName = getFileName(filePart);

     

            OutputStream out = null;

            InputStream filecontent = null;

            final PrintWriter writer = response.getWriter();

     

            try {

                out = new FileOutputStream(new File(path + File.separator
                        + fileName));
                filecontent = filePart.getInputStream();

                int read = 0;
                final byte[] bytes = new byte[1024];

                while ((read = filecontent.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }

                writer.println("New file " + fileName + " created at " + path);

                LOGGER.log(Level.INFO, "File{0}being uploaded to {1}",

                        new Object[]{fileName, path});

            } catch (FileNotFoundException fne) {

                writer.println("You either did not specify a file to upload or are "

                        + "trying to upload a file to a protected or nonexistent "

                        + "location.");

                writer.println("<br/> ERROR: " + fne.getMessage());

     

                LOGGER.log(Level.SEVERE, "Problems during file upload. Error: {0}",

                        new Object[]{fne.getMessage()});

            } finally {

                if (out != null) {

                    out.close();

                }

                if (filecontent != null) {

                    filecontent.close();

                }

                if (writer != null) {

                    writer.close();

                }

            }

        }

     

        private String getFileName(final Part part) {

            final String partHeader = part.getHeader("content-disposition");

            LOGGER.log(Level.INFO, "Part Header = {0}", partHeader);

            for (String content : part.getHeader("content-disposition").split(";")) {

                if (content.trim().startsWith("filename")) {

                    return content.substring(

                            content.indexOf('=') + 1).trim().replace("\"", "");

                }

            }

            return null;

        }

       

        private void printFeedBackInfo(HttpServletResponse response,String info) throws IOException{

            PrintWriter writer = response.getWriter();

            writer.println(info);

            writer.flush();

        }

    }

     

     

     

     

    (b) html form

    <form method="post" action="/UploadServlet_demo3" enctype="multipart/form-data" >

        Directory:  <input type="text" name="targetDirectory" value="/home/ybxiang/file/" size="60" /><br />

        File:<input type="file" name="file1" id="file1" /> <br/>

        File:<input type="file" name="file2" id="file2" /> <br/>

        <input type="submit" value="Upload" name="upload" id="upload" />

    </form>