sourav
sourav

Reputation: 109

How to use custom struts.multipart.parser

I want to implement a custom Struts2 MultiPartRequest to implement progressive file upload, by setting the progress listener.

I have written my custom FileUploadMultipartRequest by implementing the MultiPartRequest that belongs to Core-struts2.

public class FileUploadMultipartRequest implements MultiPartRequest {

    static final Log log = LogFactory.getLog(MultiPartRequest.class);

    // maps parameter name -> List of FileItem objects
    private Map<String, List<FileItem>> files = new HashMap<String, List<FileItem>>();
    // maps parameter name -> List of param values
    private Map<String, List<String>> params = new HashMap<String, List<String>>();
    // any errors while processing this request
    private List<String> errors = new ArrayList<String>();

    private long maxSize;

    @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
    public void setMaxSize(String maxSize) {

        this.maxSize = Long.parseLong(maxSize);
    }

    /**
     * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
     * multipart classes (see class description).
     *
     * @param saveDir        the directory to save off the file
     * @param servletRequest the request containing the multipart
     * @throws java.io.IOException  is thrown if encoding fails.
     */
    public void parse(HttpServletRequest servletRequest, String saveDir) throws IOException {

        DiskFileItemFactory fac = new DiskFileItemFactory();
        // Make sure that the data is written to file
        fac.setSizeThreshold(0);

        if (saveDir != null) {

            fac.setRepository(new File(saveDir));
        }

        ProgressMonitor monitor = null;

        // Parse the request
        try {

            ServletFileUpload upload = new ServletFileUpload(fac);

            upload.setSizeMax(maxSize);

            monitor = new ProgressMonitor();
            upload.setProgressListener(monitor);
            servletRequest.getSession().setAttribute(ProgressMonitor.SESSION_PROGRESS_MONITOR, monitor);
            ...
        }
    }
    ...
}

And am setting the properties in the struts.xml

<constant name="struts.multipart.parser" value="com.cloudlabz.service.web.action.FileUploadMultipartRequest " />
<constant name="struts.multipart.maxSize" value="504857600" />

Though I have set my custom MultipartRequestHandeler in the struts.xml, but still Struts 2 executing its own JakartaMultiPartRequest (Struts2 default parser to handle the multipart request) class not my custom FileUploadMultipartRequest class.

Please suggest me some way to solve it.

Upvotes: 2

Views: 6131

Answers (3)

Lukasz Lenart
Lukasz Lenart

Reputation: 1017

It supposed be like this:

<struts>
  <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
        name="jakartax"
        class="com.cloudlabz.service.web.action.FileUploadMultipartRequest"
        scope="prototype" />

  <constant name="struts.multipart.handler" value="jakartax" /> 
</struts>

Upvotes: 0

Umesh Awasthi
Umesh Awasthi

Reputation: 23587

If you are using Struts 2 version 2.1.8 + than in that case all you need to correct the struts.multipart.parser to struts.multipart.handler something like

<constant name="struts.multipart.handler"
          value="com.cloudlabz.service.web.action.FileUploadMultipartRequest" /> 

in your case jakarta will do just what struts-plugin.xml configuration file with the same bean definition will do.

For the earlier version there seems one approach, create a plugin say MycustomFileUpload. Put in under WEB-INF/lib, make sure that the jar file should have the classes and a struts-plugin.xml file.

add the following entry to struts-plugin.xml

<struts>
       <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
             name="jakartax"
             class="com.cloudlabz.service.web.action.FileUploadMultipartRequest"
             scope="default" />
</struts>

In this case you need not to define the constant in your struts.xml file.Hope this will work for you.

Upvotes: 4

luci3n
luci3n

Reputation: 11

I've just implemented a solution similar to this with 2.3.4, to have a progress meter for uploads. The easiest way is to make a copy of JakartaMultiPartRequest and rename it say MonitoredMultiPartRequest.

Then change the function parseRequest, to this:

private List<FileItem> parseRequest(HttpServletRequest servletRequest,
                                    String saveDir) throws FileUploadException {

   DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);

   ServletFileUpload upload = new ServletFileUpload(fac);
   upload.setSizeMax(maxSize);

   ProgressMonitor monitor = new ProgressMonitor();
   upload.setProgressListener(monitor);
   servletRequest.getSession().setAttribute(ProgressMonitor.SESSION_PROGRESS_MONITOR, monitor);

   return upload.parseRequest(createRequestContext(servletRequest));
}

This adds the progressmonitor to the listener (i based mine on this, then in your struts.xml add the following

<!-- Custom multipart parser with monitoring for progress bar -->
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="monitored" class="com.stackoverflow.multipart.MonitoredMultiPartRequest" scope="default" />
<constant name="struts.multipart.handler" value="monitored" />

As you can see I am overrding the standard values see the struts-default.xml here https://cwiki.apache.org/WW/struts-defaultxml.html where you can see how it is configured

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/>
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" />
<constant name="struts.multipart.handler" value="jakarta" />

Upvotes: 1

Related Questions