gmustudent
gmustudent

Reputation: 2209

Understand Working File Upload Solution

I've written the method below that is called by my doPost method to parse multipart/form-data given in the request. It all works great, I just don't really understand what is going on. If anyone could break down the three lines in my try I would really appreciate it. I've read through the Apache Commons File Upload documentation but it's just not making sense to me and I hate writing code that I do not fully understand. In particular, I would like to know what is actually happening when the factory and upload objects are created.

public static List<FileItem> parseFormRequest(HttpServletRequest request)
{
    List<FileItem> items = null;

    try 
    {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        items = upload.parseRequest(request);
    } 
    catch (FileUploadException error) 
    {
        System.out.println("UploadFileServlet - Error With File Parsing - " + error.getMessage());
    }

    return items;
}

BONUS HELP!

I also get a warning under upload.parseRequest(request) that says Type safety: The expression of type List needs unchecked conversion to conform to List<FileItem>. If anyone could explain this too that would really help me get what I've done. Thanks

enter image description here

Upvotes: 2

Views: 2663

Answers (3)

user3094213
user3094213

Reputation: 1

I need the java code that is used to invoke this function... I need the Servlet code that is used to add parameters to the HttpServletRequest

Upvotes: -1

mhaller
mhaller

Reputation: 14232

The factory is just a helper, i'll explain later. The main work is done by the ServletFileUpload.

ServletFileUpload will scan through all the uploaded files (using an Iterator which parses the MIME stuff and knows how to deal with the boundary markers, content length etc.).

For each uploaded file, the parse method asks the FileItemFactory to create a local representation for the uploaded file and then copies the contents from memory (e.g. from the HTTP POST request, which is held in memory) to the actual file on disk.

Simplified, the procedure is as follows:

  • Get next uploaded file
  • Ask factory for a local file ("FileItem")
  • Copy content from in-memory (from HttpServletRequest) to local file (a java.io.File in case of a DiskFileItemFactory)
  • Loop until end of HTTP request is reached

See the sources of the following classes for details

  • org.apache.commons.fileupload.FileUploadBase.parseRequest(RequestContext)
  • org.apache.commons.fileupload.FileUploadBase.FileItemIteratorImpl.FileItemStreamImpl

This design allows to switch to another storage facility for files, for example: You could replace the DiskFileItemFactory with your own DatabaseFileItemFactory, so the uploaded files get stored in a database instead of a local file on the server. The code changes would only affect a single line and the rest of commons-fileupload can be use as-is (e.g. the parsing of the HTTP request, the iterating over the uploaded files etc.)

For the second question: commons-fileupload seems to be Java 1.4 compatible, so the return type of parseRequest() is actually an un-typed java.util.List - it's missing the declaration that the list only contains FileItem objects (e.g. java.util.List<FileItem>). Since you declared your variable items to be of type List<FileItem>, the Java compiler warns you about this mismatch.

In this case, you did it correctly and you may ignore the warning by adding the following:

@SuppressWarnings( "unchecked" )
public static List<FileItem> parseFormRequest(HttpServletRequest request)
{
   ...

Upvotes: 3

hvgotcodes
hvgotcodes

Reputation: 120198

You need to spend some time in the documentation.

From what I can gather, the ServletFileUpload instance uses the factory you supplied to actually create the file instances that are in the request. You used a factory that writes the files to disk; there are other options though (e.g. memory). By specifying the factory, you are specifying the types of Files that are created.

When you call

upload.parseRequest(request)

the ServletFileUpload instance goes thru the request data and actually creates the files it finds, using the factory, and returns them to you in a list.

If you look at the parseRequest documentation you will notice that that method only returns a List. In your code, you are assigning that returned list to a List<FileItem>. That requires a cast, which is why you get the compiler warning.

Upvotes: 0

Related Questions