sdoca
sdoca

Reputation: 8042

Lose HttpServletRequest Parts After Reading Them

I have a servlet that receives an uploaded file. We've been having issues with a certain client's request not having a file attached or so the servlet thinks. The upload servlet is a replacement for an old one and we're using the Apache Commons FileUpload library to parse the file from the request. The old code uses the JavaZoom library. The requests client we're having issues with work perfectly fine in the old code.

In order to troubleshoot the problem, I added a bunch of logging to look at the request headers and parts to compare requests from a client that works with the one that doesn't. This is a snippet of how I'm looking at the parts:

Collection<Part> parts = request.getParts();

for(Part part : parts)                
{
    String partName = part.getName();

    log.debug("Part=" + partName);

    Collection<String> headerNames = part.getHeaderNames();

    for(String headerName : headerNames)
    {
        String headerValue = part.getHeader(headerName);                    
        log.debug(headerName + "=" + headerValue);

        InputStream inputStream = part.getInputStream();                    
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuilder builder = new StringBuilder();

        try 
        {
            for(String line=bufferedReader.readLine(); line!=null; line=bufferedReader.readLine()) 
            {
                builder.append(line);
                builder.append('\n');
            }
        } 

        catch (IOException ignore) 
        {
            // empty
        }
        finally
        {
            inputStream.reset();
        }

        log.debug("InputStream=" + builder.toString());
    }
}

All this code works fine and I get the logging I'm expecting. However, this next bit of code doesn't act as expected:

if (isMultipart)
{
    // Create a factory for disk-based file items
    FileItemFactory factory = new DiskFileItemFactory();

    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(factory);

    @SuppressWarnings("rawtypes")
    List items = null;

    // Parse the request
    try
    {
        items = upload.parseRequest(request);
        log.debug("items=" + items);
    }
    catch (FileUploadException ex)
    {
        log.warn("Error parsing request", ex);
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
    }

the items variable is empty when it's logged. If I comment out the code for logging the request parts, this bit of code works and the items variable contains the uploaded file.

I can only assume that the act of getting/reading the parts from the request somehow removes them from it and are no longer available for further processing. Is there some way to read them for logging purposes and still retain them in the request for further processing?

Upvotes: 0

Views: 1476

Answers (1)

Ramesh PVK
Ramesh PVK

Reputation: 15446

The Collection<Part> parts = request.getParts(); is an Sevlet 3.0 API which is replacement for Commons Apache File Upload API.

You should be using only one of the two methods. Both have the support for processing uploaded files and parameters along with it.

Here is the Example for File Upload Using Servlet 3.0

The problem you are facing is because you are invoking this Collection<Part> parts = request.getParts(); request will consume the request input stream. And then you are using Apache Commons API to read the parts again. Because the stream is already read you are seeing no parts are available.

References for Servlet 3.0 File Upload:

Upvotes: 2

Related Questions