7 Replies Latest reply on Apr 3, 2013 10:40 AM by jfclere

    multiple file upload

    emeuwese

      I am using JBoss AS 7.1.1. and the multipart implementation in HttpServletRequest is not working as I expected. Is the implementation of getParts() : Collection<Part> and getPart(name) : Part in HttpServletRequest correct?


      getParts() returns a collect with parts. When the parts have the same name then only the last part can be found in the list. The other parts are not accessable at all. Parts have the same name when input elements in a html form have the attribute multiple="multiple". This attribute allows selection of multiple items.

      getPart(name) returns only one part even though there could be multiple parts with the name. So should their not be a method getParts(name) : Collection<Part> similar to getHeader(name:String):String and getHeaders(name:String):Enumeration<String>.

       

       

      Take for example the following html form.

       

      ...
      <form method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/upload">
         <input type="file" name="images" multiple="multiple" accept="image/png" />
         <input type="submit" />
      </form>
      ...
      

       

      Most browsers like Chrome 25, IE 10, Opera 12 are sending it like the following.

       

      ...
      Content-Type:  multipart/form-data; boundary=----WebKitFormBoundaryI21oWgJ0TlNSk3YA
      ...
      ------WebKitFormBoundaryI21oWgJ0TlNSk3YA Content-Disposition: form-data; name="images"; filename="test1.png" Content-Type: image/png
      ...
      ------WebKitFormBoundaryI21oWgJ0TlNSk3YA Content-Disposition: form-data; name="images"; filename="test2.png" Content-Type: image/png
      ...
      ------WebKitFormBoundaryI21oWgJ0TlNSk3YA Content-Disposition: form-data; name="images"; filename="test3.png" Content-Type: image/png
      ...
      ------WebKitFormBoundaryI21oWgJ0TlNSk3YA--
      

       

      Which has as result that the following code only can access the image file with the name test3.png

       

       

      @WebServlet(urlPatterns={"/upload"})
      @MultipartConfig(location="/tmp")
      public class UploadServlet extends HttpServlet {
      
         @Override
         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
            Part imagesPart = request.getPart("images"); // returns only the last part with test3.png
            Logger.getLogger(UploadServlet.class.getName()).log(Level.INFO, imagesPart.getHeader("Content-Disposition"));
      
            for(Part part : request.getParts()) { // getParts() returns only 1 part, that part is the part with test3.png
               Logger.getLogger(UploadServlet.class.getName()).log(Level.INFO, imagesPart.getHeader("Content-Disposition"));
            }
         }
      }
      
        • 1. Re: multiple file upload
          jaikiran

          I'm not sure what the expected behaviour of getParts() method is when more than one part is named the same - like in this case. But the implementation clearly doesn't take this into account:

           

          /**
               * Parse multipart.
               */
              protected void parseMultipart()
                  throws IOException, ServletException {
                  
                  parts = Collections.emptyMap();
          
                  ...
          
                  parts = new HashMap<String, Part>();
                  try {
                      for (FileItem fileItem : upload.parseRequest(getRequest())) {
                          if (fileItem.getName() == null) {
                              coyoteRequest.getParameters().addParameterValues
                                  (fileItem.getFieldName(), new String[] {fileItem.getString()});
                          }
                          parts.put(fileItem.getFieldName(), new StandardPart(fileItem, config));
                      }
                  } catch(FileSizeLimitExceededException e) {
                      throw MESSAGES.multipartProcessingFailed(e);
                  } catch(SizeLimitExceededException e) {
                      throw MESSAGES.multipartProcessingFailed(e);
                  } catch (FileUploadException e) {
                      throw MESSAGES.multipartIoProcessingFailed(e);
                  }
          

           

          I'll move this to JBossWeb forum where someone more knowledgeable about this, might be able to help.

          1 of 1 people found this helpful
          • 2. Re: multiple file upload
            jaikiran

            Moved to JBossWeb forum.

            • 3. Re: multiple file upload
              jfclere

              According to http://www.w3.org/TR/html401/interact/forms.html using name as key for the HashMap looks wrong...

              1 of 1 people found this helpful
              • 4. Re: multiple file upload
                emeuwese

                The HashMap<String,Part> parts in org.apache.catalina.connector.Request in Jboss Web 7.2.0 allows only one part to be mapped with a certain name which is not so usefull in this case.

                 

                A simple class which implements Map and has internal a Map<String, Collection<Part>> solved the issue for me. I included my patch in the attachment. An other solution would be to implement it like Tomcat 7.x. which I also included in the attachement. Tomcat uses an ArrayList<Parts> for the field parts.

                 

                For getParts() it could return all values. Part getPart(String name) could return the first value mapped to the key. Then a new method Collection<Part> getPart(String name) which returns all the values which are mapped to a single key.

                 

                I think this could be a solution which still fits the description in the JSR 315 specification. The description of getParts() and getPart() in JSR 315 Java Servlet 3.0 Specification http://jcp.org/aboutJava/communityprocess/mrel/jsr315/index.html doesn't say explicitly that name is unique and doesn't mention that there could be parts with the same name.

                • 5. Re: multiple file upload
                  jfclere

                  It is fix in next jbossweb version (r2179). Please open a JIRA to get it in the current version.

                  See https://source.jboss.org/changelog/JBossWeb?cs=2179

                  • 6. Re: multiple file upload
                    emeuwese

                    I could as individual make a suggestion  to change section 3.2 FileUpload so that HttpServletRequest should also make the data available through the method public Collection<Part> getParts(String name) and that the text should contain something like; that there could be multiple parts with the same name, in the Proposed Final Draft of JSR 340: Java Servlet 3.1 Specification http://jcp.org/en/jsr/detail?id=340 .

                     

                    May be JBoss could also make a suggestion to change section 3.2 FileUpload.

                    • 7. Re: multiple file upload
                      jfclere

                      you can use public Collection<Part> getParts() to get all the parts.