【问题标题】:Struts 2 File Upload Interceptor configuration problemsStruts 2 File Upload Interceptor 配置问题
【发布时间】:2009-09-18 17:11:07
【问题描述】:

尝试在我的应用程序中配置 Struts 2 文件上传拦截器时遇到两个问题。我想更改参数maximumSize(默认值是2 MB,我需要它是5 MB)和消息资源struts.messages.error.file.too.large(应用程序语言环境是pt_BR,所以消息是葡萄牙语,而不是英语)。

应用当前配置如下:

struts.properties

struts.locale=pt_BR 
struts.custom.i18n.resources=MessageResources

struts.xml

<package name="default" namespace="/" extends="struts-default">
    <interceptors>
        <interceptor name="login" class="br.com.probank.interceptor.LoginInterceptor"/>
        <interceptor-stack name="defaultLoginStack">
            <interceptor-ref name="login" />
            <interceptor-ref name="defaultStack"/>
        </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="defaultLoginStack" />
    ...
</package>

...
<package name="proposta" namespace="/proposta" extends="default">
    <action name="salvarAnexoProposta" method="salvarAnexoProposta" class="br.com.probank.action.AnexoPropostaAction">
        <interceptor-ref name="defaultLoginStack">
            <param name="fileUpload.maximumSize">5242880</param>
        </interceptor-ref>
        <result name="success">/jsp/listagemAnexosPropostaForm.jsp</result>
        <result name="input">/jsp/crudAnexoPropostaForm.jsp</result>
        <result name="error">/jsp/error.jsp</result>
        <result name="redirect" type="redirect">${redirectLink}</result>
    </action>
</package>

MessageResources.properties

...
struts.messages.error.file.too.large=O tamanho do arquivo...

我的 Action 实现和 JSP 代码没有什么特别之处。他们遵循找到的示例http://struts.apache.org/2.1.6/docs/file-upload-interceptor.html。当我尝试上传超过 5 MB 的文件时,应用程序显示消息“请求被拒绝,因为其大小 (6229458) 超过了配置的最大值 (2097152)” - 默认文件上传消息,默认为 maximumSize 值。

我尝试将消息资源struts.messages.error.file.too.large 放在 struts-messages.properties 中,但之后消息没有改变。配置文件上传拦截器的正确方法是什么?我正在使用 Struts 2 2.1.7。提前致谢。

【问题讨论】:

  • 刚刚找到了一种更改上传大小限制的方法。 :) 我将struts.properties 文件中的struts.multipart.maxSize 属性更改为所需的值。但是本地化错误消息的问题仍然存在......

标签: file-upload configuration struts2 interceptor interceptorstack


【解决方案1】:

终于解开了整个谜题! struts.xmlMessageResource.properties 已正确配置。问题是 struts.multipart.maxSize。该值必须大于所需的上传限制(在我的应用程序中为 5242880),因此我将其设置为 10000000。如果 struts.multipart.maxSize 值等于或小于 fileUpload.maximumSize,Struts 2 用于上传的库将停止在文件上传拦截器有机会完成其工作之前的上传过程(并写入错误消息)。

【讨论】:

    【解决方案2】:

    您提供的解决方案并不完全正确,如果我想要严格的上传限制以及 i18n,这将不起作用。为此,我还为 strut2 创建了一个问题。请查看以下链接https://issues.apache.org/jira/browse/WW-3177。它应该在 struts2.1.9 中修复,并且已经分配给一个 struts 团队成员。

    在这两者之间,我正在使用 hack。我浏览了struts2的源代码,找到了FileUploadInterceptor的代码。使用该代码,我创建了自己的代码。这是下面的代码。您可以在上面的链接中找到问题的详细信息。希望这会有所帮助。

    import java.io.File;
    import java.util.*;
    
    import javax.servlet.http.HttpServletRequest;
    import org.apache.struts2.ServletActionContext;
    import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.ActionProxy;
    import com.opensymphony.xwork2.ValidationAware;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    import com.opensymphony.xwork2.util.LocalizedTextUtil;
    import com.opensymphony.xwork2.util.TextParseUtil;
    import com.opensymphony.xwork2.util.logging.Logger;
    import com.opensymphony.xwork2.util.logging.LoggerFactory;
    
    
    public class CustomFileUploaderInterceptor extends AbstractInterceptor {
    
        private static final long serialVersionUID = -4764627478894962478L;
    
        protected static final Logger LOG =           LoggerFactory.getLogger(CustomFileUploaderInterceptor.class);
        private static final String DEFAULT_MESSAGE = "no.message.found";
    
        protected boolean useActionMessageBundle;
    
        protected Long maximumSize;
        protected Set<String> allowedTypesSet = Collections.emptySet();
        protected Set<String> allowedExtensionsSet = Collections.emptySet();
    
        public void setUseActionMessageBundle(String value) {
            this.useActionMessageBundle = Boolean.valueOf(value);
        }
    
        /**
         * Sets the allowed extensions
         *
         * @param allowedExtensions A comma-delimited list of extensions
         */
        public void setAllowedExtensions(String allowedExtensions) {
            allowedExtensionsSet = TextParseUtil.commaDelimitedStringToSet(allowedExtensions);
        }
    
        /**
         * Sets the allowed mimetypes
         *
         * @param allowedTypes A comma-delimited list of types
         */
        public void setAllowedTypes(String allowedTypes) {
            allowedTypesSet = TextParseUtil.commaDelimitedStringToSet(allowedTypes);
        }
    
        /**
         * Sets the maximum size of an uploaded file
         *
         * @param maximumSize The maximum size in bytes
         */
        public void setMaximumSize(Long maximumSize) {
            this.maximumSize = maximumSize;
        }
    
        /* (non-Javadoc)
         * @see com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
         */
        public String intercept(ActionInvocation invocation) throws Exception {
            ActionContext ac = invocation.getInvocationContext();
            Map<String, Object> params1 = ac.getParameters();
            Set<String> keySet = params1.keySet();
            for(String s : keySet){
                LOG.debug("Key: "+ s +", Value: " + params1.get(s).toString());
            }
            HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
    
            if (!(request instanceof MultiPartRequestWrapper)) {
                if (LOG.isDebugEnabled()) {
                    ActionProxy proxy = invocation.getProxy();
                    LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ac.getLocale()));
                }
    
                return invocation.invoke();
            }
    
            ValidationAware validation = null;
    
            Object action = invocation.getAction();
    
            if (action instanceof ValidationAware) {
                validation = (ValidationAware) action;
            }
    
            MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
    
            if (multiWrapper.hasErrors()) {
                String inputName = null;
                if(multiWrapper.getFileParameterNames().hasMoreElements()){
                    inputName = (String)multiWrapper.getFileParameterNames().nextElement();
    
                }
                for (String error : multiWrapper.getErrors()) {
                    if (validation != null) {
                        Object[] args = new Object[]{inputName};
                        validation.addActionError(getTextMessage(action, "struts.messages.error.file.too.large", args, ac.getLocale()));
                    }
                    LOG.error(error);
                }
            }
    
            // bind allowed Files
            Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
            while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
                // get the value of this input tag
                String inputName = (String) fileParameterNames.nextElement();
    
                // get the content type
                String[] contentType = multiWrapper.getContentTypes(inputName);
    
                if (isNonEmpty(contentType)) {
                    // get the name of the file from the input tag
                    String[] fileName = multiWrapper.getFileNames(inputName);
    
                    if (isNonEmpty(fileName)) {
                        // get a File object for the uploaded File
                        File[] files = multiWrapper.getFiles(inputName);
                        if (files != null && files.length > 0) {
                            List<File> acceptedFiles = new ArrayList<File>(files.length);
                            List<String> acceptedContentTypes = new ArrayList<String>(files.length);
                            List<String> acceptedFileNames = new ArrayList<String>(files.length);
                            String contentTypeName = inputName + "ContentType";
                            String fileNameName = inputName + "FileName";
    
                            for (int index = 0; index < files.length; index++) {
                                if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
                                    acceptedFiles.add(files[index]);
                                    acceptedContentTypes.add(contentType[index]);
                                    acceptedFileNames.add(fileName[index]);
                                }
                            }
    
                            if (!acceptedFiles.isEmpty()) {
                                Map<String, Object> params = ac.getParameters();
    
                                params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
                                params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
                                params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
                            }
                        }
                    } else {
                        LOG.error(getTextMessage(action, "struts.messages.invalid.file", new Object[]{inputName}, ac.getLocale()));
                    }
                } else {
                    LOG.error(getTextMessage(action, "struts.messages.invalid.content.type", new Object[]{inputName}, ac.getLocale()));
                }
            }
    
            // invoke action
            String result = invocation.invoke();
    
            // cleanup
            fileParameterNames = multiWrapper.getFileParameterNames();
            while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
                String inputValue = (String) fileParameterNames.nextElement();
                File[] files = multiWrapper.getFiles(inputValue);
    
                for (File currentFile : files) {
                    if (LOG.isInfoEnabled()) {
                        LOG.info(getTextMessage(action, "struts.messages.removing.file", new Object[]{inputValue, currentFile}, ac.getLocale()));
                    }
    
                    if ((currentFile != null) && currentFile.isFile()) {
                        currentFile.delete();
                    }
                }
            }
    
            return result;
        }
    
        /**
         * Override for added functionality. Checks if the proposed file is acceptable based on contentType and size.
         *
         * @param action      - uploading action for message retrieval.
         * @param file        - proposed upload file.
         * @param contentType - contentType of the file.
         * @param inputName   - inputName of the file.
         * @param validation  - Non-null ValidationAware if the action implements ValidationAware, allowing for better
         *                    logging.
         * @param locale
         * @return true if the proposed file is acceptable by contentType and size.
         */
        protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) {
            boolean fileIsAcceptable = false;
    
            // If it's null the upload failed
            if (file == null) {
                String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[]{inputName}, locale);
                if (validation != null) {
                    validation.addFieldError(inputName, errMsg);
                }
    
                LOG.error(errMsg);
            } else if (maximumSize != null && maximumSize < file.length()) {
                String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[]{inputName, filename, file.getName(), "" + file.length()}, locale);
                if (validation != null) {
                    validation.addFieldError(inputName, errMsg);
                }
    
                LOG.error(errMsg);
            } else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
                String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
                if (validation != null) {
                    validation.addFieldError(inputName, errMsg);
                }
    
                LOG.error(errMsg);
            } else if ((! allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) {
                String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
                if (validation != null) {
                    validation.addFieldError(inputName, errMsg);
                }
    
                LOG.error(errMsg);
            } else {
                fileIsAcceptable = true;
            }
    
            return fileIsAcceptable;
        }
    
        /**
         * @param extensionCollection - Collection of extensions (all lowercase).
         * @param filename            - filename to check.
         * @return true if the filename has an allowed extension, false otherwise.
         */
        private static boolean hasAllowedExtension(Collection<String> extensionCollection, String filename) {
            if (filename == null) {
                return false;
            }
    
            String lowercaseFilename = filename.toLowerCase();
            for (String extension : extensionCollection) {
                if (lowercaseFilename.endsWith(extension)) {
                    return true;
                }
            }
    
            return false;
        }
    
        /**
         * @param itemCollection - Collection of string items (all lowercase).
         * @param item           - Item to search for.
         * @return true if itemCollection contains the item, false otherwise.
         */
        private static boolean containsItem(Collection<String> itemCollection, String item) {
            return itemCollection.contains(item.toLowerCase());
        }
    
        private static boolean isNonEmpty(Object[] objArray) {
            boolean result = false;
            for (int index = 0; index < objArray.length && !result; index++) {
                if (objArray[index] != null) {
                    result = true;
                }
            }
            return result;
        }
    
        private String getTextMessage(String messageKey, Object[] args, Locale locale) {
            return getTextMessage(null, messageKey, args, locale);
        }
    
        private String getTextMessage(Object action, String messageKey, Object[] args, Locale locale) {
            if (args == null || args.length == 0) {
                if ( action != null && useActionMessageBundle) {
                    return LocalizedTextUtil.findText(action.getClass(), messageKey, locale);
                }
                return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);                        
            } else {
                if ( action != null && useActionMessageBundle) {
                    return LocalizedTextUtil.findText(action.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
                }
                return LocalizedTextUtil.findText(this.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      在您的struts.xml 中试试这个,xxxxxxxx 是限制:

      <constant name="struts.multipart.maxSize" value="xxxxxxxxx" />
      

      【讨论】:

        【解决方案4】:

        首先在你的动作文件中使用 validate 方法............

        public void validate(){
        
          if(getFileUpload() !=null){
        
           System.out.println("======File size validation before upload: size in bytes: "+getFileUpload().length());
        
            if(getFileUpload().length()>202400){   
        
        //Give the size in bytes whatever you want to take
        
            addActionError("File is too large ! Select less than 200Kb file");
        
              }else{
        
            addActionMessage("File Uploaded successfully!");
        
             }
           }
        }
        

        完整代码请访问http://knowledge-serve.blogspot.com/2011/10/upload-file-using-in-struts-2.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-19
          • 2011-10-01
          • 2017-07-06
          • 1970-01-01
          • 2017-08-22
          • 1970-01-01
          • 1970-01-01
          • 2014-06-11
          相关资源
          最近更新 更多