Search code examples
javafile-uploadportletapache-commons-fileupload

GenericPortlet - FileUpload platform independent


Short question : how can I handle file upload in a javax.portlet.GenericPortlet:serveResource method implementation keeping the code portal platform independent?

Long question : I'm creating an implementation of a javax.portlet.GenericPortlet. This portlet has to be deployed on WebSphere Portal and Liferay Portal. In the serveResource method of this portlet I read a multipart/form-data request. As far as I know in liferay I can handle fileupload this way:

// save the request attached file from the client
UploadPortletRequest uploadRequest = PortalUtil.getUploadPortletRequest(resourceRequest);
String fileName = uploadRequest.getFileName(paramFile);
InputStream inputStream = uploadRequest.getFileAsStream(paramFile, true);

the problem with this code snippet is that it depends on Liferay portal and obviusly it is going to break out on another portal version.

I have seen the library apache commons fileupload but I cannot figure out how to use it, particularly in the serveResource method. I found many examples with the file upload in javax.portlet.GenericPortlet:processAction, but none in the serveResource. For example, how can I use the simple

boolean isMultipart = PortletFileUpload.isMultipartContent(request);

in my serveResource method?


Solution

  • Finally I found a solution on my own.

    import java.io.File;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ResourceBundle;
    
    import javax.portlet.PortletRequest;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadBase;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.fileupload.servlet.ServletRequestContext;
    
    public class MyPortlet extends GenericPortlet {
    
        @Override
        public void serveResource(ResourceRequest request, ResourceResponse resourceResponse) throws PortletException, IOException {
    
            final HttpServletRequest originalHttpServletRequest = portalService.getOriginalHttpServletRequest(request);
            final boolean multipartContent = FileUploadBase.isMultipartContent(new ServletRequestContext(originalHttpServletRequest));
            if (multipartContent) {
                // Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
                // Set factory constraints
                factory.setSizeThreshold(yourMaxMemorySize);
                factory.setRepository(yourTempDirectory);
                // Create a new file upload handler
                ServletFileUpload upload = new ServletFileUpload(factory);
                // Set overall request size constraint
                upload.setSizeMax(yourMaxRequestSize);
    
                List<FileItem> items = upload.parseRequest(originalHttpServletRequest);
    
                // Process the uploaded items
                Iterator<FileItem> iter = items.iterator();
                while (iter.hasNext()) {
                    FileItem thisItem = (FileItem) iter.next();
                    final String fieldName = thisItem.getFieldName();
                    // if an element is a form field
                    if (thisItem.isFormField()) {
                        if (fieldName.equals("yourfieldformparam")) {
                            String value = thisItem.getString();
                            // Do something with the value
                        }
                    } else {
                        // if its an attachment you can do...
                        String fileName = item.getName();
                        String contentType = item.getContentType();
                        boolean isInMemory = item.isInMemory();
                        long sizeInBytes = item.getSize();
    
                        File fileOut = File.createTempFile(IMieiPagamentiConstants.FILE_PREFIX, null);
                        // delete on jvm exit
                        fileOut.deleteOnExit();
                        // write the file
                        thisItem.write(fileOut);
    
                        //...
                    }
                }
            }
        }
    }
    

    The portalService.getOriginalHttpServletRequest(request); is a method that gives you the portal-specific underneath HttpServletRequest for the ResourceRequest. For example, in Liferay:

    @Override
        public HttpServletRequest getOriginalHttpServletRequest(PortletRequest request) {
            return PortalUtil.getOriginalServletRequest(getHttpServletRequest(request));
        }