2 Replies Latest reply on Sep 24, 2013 1:57 PM by max.weinhart

    rich:fileUpload restrict filesize: maxRequestSize does not work

    max.weinhart

      I am using

      JBoss EPP 5.2.0 with

      JSF 1.2_14 and

      RichFaces 3.3.2.SR1 and

      portletbridge 2.0.0.FINAL.

       

      I want to restict the filesize of uploaded files. I have tried following:

       

      xhtml:

      <rich:fileUpload   id="uploader" 
      fileUploadListener="#{controller.fileUploadlistener}"

      immediateUpload="true"
      allowFlash="false"
      maxFilesQuantity="#{controller.uploadsLeft}"
      acceptedTypes="pdf,jpg,tif,pgm,pbm,png">
      <a4j:support event="onuploadcomplete"
      reRender="uploadedFiles" />
      </rich:fileUpload>

      web.xml:

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        
      xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        
      version="2.5">
        
      <display-name>Example</display-name>
      <context-param>
        
      <param-name>org.ajax4jsf.COMPRESS_SCRIPT</param-name>
        
      <param-value>false</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        
      <param-value>.xhtml</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
        
      <param-value>org.jboss.portletbridge.application.FaceletPortletViewHandler</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.richfaces.LoadStyleStrategy</param-name>
        
      <param-value>DEFAULT</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.richfaces.LoadScriptStrategy</param-name>
        
      <param-value>DEFAULT</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
        
      <param-value>rfRes</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.richfaces.SKIN</param-name>
        
      <param-value>blueSky</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
        
      <param-value>false</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>javax.portlet.faces.renderPolicy</param-name>
        
      <param-value>NEVER_DELEGATE</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.richfaces.fileUpload.maxRequestSize</param-name>
        
      <param-value>2000000</param-value>
        
      </context-param>
        
      <context-param>
        
      <param-name>org.richfaces.fileUpload.createTempFiles</param-name>
        
      <param-value>false</param-value>
      </context-param>
      <servlet>
        
      <servlet-name>FacesServlet</servlet-name>
        
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        
      <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        
      <servlet-name>FacesServlet</servlet-name>
        
      <url-pattern>/faces/*</url-pattern>
      </servlet-mapping>
      <filter>
        
      <display-name>Ajax4jsf Filter</display-name>
        
      <filter-name>ajax4jsf</filter-name>
        
      <filter-class>org.ajax4jsf.Filter</filter-class>
        
      <init-param>
        
      <param-name>createTempFiles</param-name>
        
      <param-value>false</param-value>
        
      </init-param>
        
      <init-param>
        
      <param-name>maxRequestSize</param-name>
        
      <param-value>2000000</param-value>
        
      </init-param>
      </filter>
      <filter-mapping>
        
      <filter-name>ajax4jsf</filter-name>
        
      <servlet-name>FacesServlet</servlet-name>
        
      <dispatcher>FORWARD</dispatcher>
        
      <dispatcher>REQUEST</dispatcher>
        
      <dispatcher>INCLUDE</dispatcher>
      </filter-mapping>
      <error-page>
        
      <exception-type>javax.portlet.PortletException</exception-type>
        
      <location>/faces/errorpages/error.xhtml</location>
      </error-page>
      <login-config>
        
      <auth-method>BASIC</auth-method>
      </login-config>

       

      Following states that it is a bug: https://issues.jboss.org/browse/PBR-241

      If I upload a file it seems that the filter is never called. The filter is only called on server startup.

       

      Without the restiction of filesize rich:fileUpload is missing a key feature.

      Is there a workaround for that?

      How can I restrict the filesize?

      Is there another existing component which does the job with restriction of filesize?

       

      After some work I have tried to solve it with a portlet-filter:

       

         public class MyResourceFilter implements ResourceFilter {

        
      public static final String MULTIPART = "multipart/";
        
      public static final String AJAX4JSF_FILTER = "org.ajax4jsf.Filter";
        
      public static final String PARAM_MAX_REQUEST_SIZE = "maxRequestSize";

        
      private static final Logger LOGGER = LoggerFactory.getLogger(MyResourceFilter.class);

        
      private int uploadLimit = 0;

        
      @Override
        
      public void destroy() {

        
      }

        
      @Override
        
      public void init(FilterConfig config) throws PortletException {
        
      String maxRequestSizeParam = config.getInitParameter(PARAM_MAX_REQUEST_SIZE);
        
      if (maxRequestSizeParam != null) {
        
      try {
        uploadLimit
      = Integer.parseInt(maxRequestSizeParam);
        
      } catch (NumberFormatException nfe) {
        LOGGER
      .warn("invalid Filter init parameter value in portlet.xml: " + PARAM_MAX_REQUEST_SIZE + " - " + maxRequestSizeParam);
        
      }
        
      }
        
      }

        
      @Override
        
      public void doFilter(ResourceRequest resourceRequest, ResourceResponse resourceResponse, FilterChain filterChain)
        
      throws IOException, PortletException {
        
      String resourceKey = resourceRequest.getParameter(PortletResourceBuilder.RFRES);
        
      if (null == resourceKey) {
        
      // Handle File Upload
        
      if (isMultipartContent(resourceRequest)) {
        
      String uid = resourceRequest.getParameter(FileUploadConstants.UPLOAD_FILES_ID);
        
      ResourceRequestWrapper resourceRequestWrapper = new ResourceRequestWrapper(resourceRequest);
        
      String contentLength = resourceRequestWrapper.getHeader("Content-Length");
        
      int contentLengthInt = Integer.parseInt(contentLength);
        
      if (contentLength != null && uploadLimit > 0
        
      && contentLengthInt > uploadLimit) {
        
      throw new FileUploadException("Multipart request is larger than allowed size");
        
      }
        
      }
        
      }
        filterChain
      .doFilter(resourceRequest, resourceResponse);
        
      }

        
      private static boolean isMultipartContent(ResourceRequest request) {
        
      boolean vReturn = false;
        
      String contentType = request.getContentType();
        
      if (contentType == null) {
        vReturn
      = false;
        
      } else if (contentType.toLowerCase().startsWith(MULTIPART)) {
        vReturn
      = true;
        
      }
        
      return vReturn;
        
      }
        
      }

       

      portlet.xml:

       

          <filter>
            
      <filter-name>MyResourceFilter</filter-name>
            
      <filter-class>my.package.MyResourceFilter</filter-class>
            
      <lifecycle>RESOURCE_PHASE</lifecycle>
            
      <init-param>
            
      <name>maxRequestSize</name>
            
      <value>2000000</value>
            
      </init-param>
          </filter>  


      It would be nice if anybody could review the code.

      Does it look good for you?

       

      Regards

       

      Max