8

I have a client application in Android which uses HttpURLConnection to send files to the server. The server uses the Apache Commons FileUpload API to parse the form-data values.

The HttpURLConnection sends this request:

-----------------------------4912995119421
Content-Disposition: form-data; name="deviceid"

9428103
-----------------------------4912995119421
Content-Disposition: form-data; name="countryid"

598
-----------------------------4912995119421
Content-Disposition: form-data; name="number"

98621360
-----------------------------4912995119421
Content-Disposition: form-data; name="file"; filename="2012-12-08 17.42.18.jpg"
Content-Type: image/jpeg

ÿØÿá1 Exif  II*    
      @      °      ª    
   ²              ¼       Ä   (       1    Ì   2    Ø          i‡    ì   %ˆ    \  n  SAMSUNG GT-S5360L H      H      S5360LUHLB1 2012:12:08 17:42:18  š‚    î  ?‚    ö  "ˆ       'ˆ    È    ?    0220?    þ  ?      ‘     ’    &  ’       
’    .        0100             @       °       >  £       ¤        ¤        ¤    6  ¤                     
   2012:12:08 17:42:18 2012:12:08 17:42:18    
     d               R98      0100                         (           ¤      T.      ÿØÿà JFIF      ÿÛ C @@ÿÛ 
-----------------------------4912995119421--

The server code:

    String contentType = request.getContentType();
    if ((contentType.indexOf("multipart/form-data") == -1)) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
    }


    long maxFileSize = (2 * 1024 * 1024);

    int maxMemSize = (2 * 1024 * 1024);

    DiskFileItemFactory factory = new DiskFileItemFactory();
    // maximum size that will be stored in memory
    factory.setSizeThreshold(maxMemSize);

    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(factory);
    // maximum file size to be uploaded.

    upload.setSizeMax(maxFileSize);

    List fileItems = upload.parseRequest(request);
    Iterator i = fileItems.iterator();


    //leo primero todas las variables.

    int deviceID = 0;
    int countryID = 0;
    String phoneNumber = "";



    while (i.hasNext()) {
        FileItem fi = (FileItem) i.next();

        if (fi.isFormField()) {
            String variable = fi.getFieldName();
            if (variable.equals("deviceid")) {
                deviceID = Integer.parseInt(fi.getString());
            } else if (variable.equals("countryid")) {
                countryID = Integer.parseInt(fi.getString());
            } else if (variable.equals("number")) {
                phoneNumber = String.valueOf(Long.parseLong(fi.getString()));
            }

        }

    }

    if (deviceID == 0 || countryID == 0 || phoneNumber.equals("")) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

The problem is in the line List fileItems = upload.parseRequest(request);. The returned list is empty and I can not get the form-data values.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
toto
  • 1,122
  • 2
  • 13
  • 26

5 Answers5

29

It will be empty at that point if you have already (implicitly) parsed the request body beforehand. The HTTP request body can be read/parsed only once (as the client has sent it only once and won't send it multiple times).

The request body will be implicitly read/parsed when you have invoked any of the following methods before feeding the request to Commons FileUpload:

request.getParameter();
request.getParameterMap();
request.getParameterNames();
request.getParameterValues();
request.getReader();
request.getInputStream();

You need to make absolutely sure that you are not calling any of those methods beforehand (also check all servlet filters to be sure).

If you've already ensured that you aren't doing that, then the only other possible causes would be an incorrect boundary header and/or using incorrect newlines (it has really to be CR+LF and thus not alone LF). You can find a concrete and proper example at the bottom of Using java.net.URLConnection to fire and handle HTTP requests, under the section "Uploading files".

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • i checked using: request.getInputStream() byte[] a = new byte[8096]; int r = 0; ServletInputStream s = request.getInputStream(); String c = ""; while ((r = s.read(a)) != -1) { c += new String(a).substring(0, r); } And received the data ok. The problem is that the commond file upload can´t parse the content. – toto Dec 14 '12 at 15:21
  • Well, if you remove that `request.getInputStream()` call, then it should work fine, exactly as explained in my answer. – BalusC Dec 14 '12 at 15:25
  • Okay, I'll assume that you are not calling any of the mentioned methods beforehand. This problem can then only mean that you didn't set the proper boundary header, or when you used the wrong newlines. You can find a concrete and proper example at the bottom of http://stackoverflow.com/a/2793153, under the section "Uploading files". – BalusC Dec 14 '12 at 15:36
  • I had a small mistake when setting: connection.setRequestProperty ("content-type", "multipart / form-data, boundary =" + boundary0); mistakenly add "-" before the boundary. – toto Dec 14 '12 at 16:02
  • I get similar problem with empty list but the problem actually was from this parameter **Locale lang** `public void uploadFile(Locale lang, ModelMap model, HttpServletRequest request, HttpServletResponse response)` I just remove this parameter and it take my whole day to figure that – Belal mazlom Apr 30 '15 at 12:42
  • @BalusC (https://stackoverflow.com/questions/49107570/fileupload-parserequestrequest-returning-null) I am facing the above mentioned issue, I have not used request still issue persist. Can you please check the mentioned link – Sachin Bankar Mar 05 '18 at 12:29
2

If spring is used, check if there is a <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> in xml file. There is a function

protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
        if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
            if (request instanceof MultipartHttpServletRequest) {
                logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
                        "this typically results from an additional MultipartFilter in web.xml");
            }
            else {
                return this.multipartResolver.resolveMultipart(request);
            }
        }
        // If not returned before: return original request.
        return request;
    }

"eats" the multipart items. It causes a three hours pain.

Tiina
  • 2,967
  • 2
  • 30
  • 55
0

I was running into this problem as well, but I couldn't find anything that specifically related to reading the request object. I finally got it to work by removing this block:

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

Apparently when I had been trying to read the request by using getParts(), I forgot to remove this. I'm a bit new to java, so I didn't know this conflicts with the ServletFileUpload#parseRequest. Anyway, once I got rid of it, the parseRequest correctly returned the array.

0

I had this same problem after trying I find that it was incompatibility of libraries, library apache server with fileupload library, so I remove the library and imported from the library server Apache.

imports:
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;

sorry my english

  • This solution does not work, since ServletFileUpload.parseRequest from tomcat requires a parameter of type RequestContext, a class from the same tomcat library, and ServletFileUpload.parseRequest from commons requires a parameter of type HttpServletRequest from the servlet API. And thus, if you change the imports, the code does not compile. – joanlofe Aug 08 '19 at 12:49
-1

my problem is apache context.xml on my linux server contains Context

allowCasualMultipartParsing="true" and my HttpServlet contains

@MultipartConfig(fileSizeThreshold=1024*1024*2,maxFileSize=1024*1024*50,maxRequestSize=1024*1024*50)

I delete it then it's working correctly. Hope this will help you.

The Hungry Dictator
  • 3,247
  • 4
  • 34
  • 47