论坛首页 Java企业应用论坛

这是不是Webwork文件上传的一个Bug?

浏览 8251 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-06-07  
我用Webwork的FileUploadInterceptor进行文件上传,表单里混合了普通的input和file input,当file input选择了文件后,一切没问题,当file input为空的时候,就会出现这个异常:

java.lang.NullPointerException
	com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest.getFileNames(CosMultiPartRequest.java:63);
	com.opensymphony.webwork.dispatcher.multipart.MultiPartRequestWrapper.getFileNames(MultiPartRequestWrapper.java:208);
	com.opensymphony.webwork.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:109);
	com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:164);
	com.opensymphony.xwork.DefaultActionProxy.execute(DefaultActionProxy.java:116);
	com.opensymphony.webwork.dispatcher.ServletDispatcher.serviceAction(ServletDispatcher.java:272);
	com.opensymphony.webwork.dispatcher.ServletDispatcher.service(ServletDispatcher.java:237);
	javax.servlet.http.HttpServlet.service(HttpServlet.java:802);
	com.alpaq.modu.web.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:170);



我想上传文件框留空应该是个很常见的需求,似乎webwork不应该忽略这一块阿。是不是我的程序的问题?其他朋友有没有碰到过这个问题?

另外,我在定义interceptor的时候,即使指定了allowedTypes和maximumSize,也是毫不起作用的。而仔细看FileUploadInterceptor的源代码,也没有发现他们有使用到这两个参数,而是委托给了Validator,可具体Validator怎么用呢?
   发表时间:2005-06-07  
这两个似乎都是bug:

http://jira.opensymphony.com/browse/WW-746

http://jira.opensymphony.com/browse/WW-761


真郁闷,一天撞上两个bug!


这两个问题似乎到目前为止还没有解决。第一个NullPointer的问题,我自己改了改它的代码,勉强先用用吧,第二个其实也可以改代码来做得,不过我想知道怎么用validator来做,这样可以为不同的action使用不同的限制条件了:



/*
 * Copyright (c); 2002-2003 by OpenSymphony
 * All rights reserved.
 */
package com.i8series.core.webwork.interceptors;

import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.dispatcher.multipart.MultiPartRequestWrapper;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.ValidationAware;
import com.opensymphony.xwork.interceptor.Interceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;


/**
 * Interceptor that is based off of {@link MultiPartRequestWrapper}. It adds the following
 * parameters, where [File Name] is the name given to the file uploaded by the HTML form:
 * <ul>
 * <li>[File Name] : File - the actual File</li>
 * <li>[File Name]ContentType : String - the content type of the file</li>
 * <li>[File Name]FileName : String - the actual name of the file uploaded (not the HTML name);</li>
 * </ul>
 * <p/>
 * You can get access to these files by merely providing setters in your action that correspond to any
 * of the three patterns above, such as setDocument(File document);, setDocumentContentType(String contentType);, etc.
 */
public class FileUploadInterceptor implements Interceptor {
    //~ Static fields/initializers /////////////////////////////////////////////

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

    //~ Instance fields ////////////////////////////////////////////////////////

    protected Long maximumSize;
    protected String allowedTypes;
    protected String disallowedTypes;

    //~ Methods ////////////////////////////////////////////////////////////////

    public void setAllowedTypes(String allowedTypes); {
        this.allowedTypes = allowedTypes;
    }

    public void setDisallowedTypes(String disallowedTypes); {
        this.disallowedTypes = disallowedTypes;
    }

    public void setMaximumSize(Long maximumSize); {
        this.maximumSize = maximumSize;
    }

    public void destroy(); {
    }

    public void init(); {
    }

    public String intercept(ActionInvocation invocation); throws Exception {
        if (!(ServletActionContext.getRequest(); instanceof MultiPartRequestWrapper);); {
            if (log.isDebugEnabled();); {
                log.debug("bypass " + invocation.getProxy();.getNamespace(); + "/" + invocation.getProxy();.getActionName(););;
            }

            return invocation.invoke();;
        }

        final Action action = invocation.getAction();;
        ValidationAware validation = null;

        if (action instanceof ValidationAware); {
            validation = (ValidationAware); action;
        }

        MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper); ServletActionContext.getRequest();;

        if (multiWrapper.hasErrors();); {
            Collection errors = multiWrapper.getErrors();;
            Iterator i = errors.iterator();;

            while (i.hasNext();); {
                String error = (String); i.next();;

                if (validation != null); {
                    validation.addActionError(error);;
                }

                log.error(error);;
            }
        }

        Enumeration e = multiWrapper.getFileParameterNames();;

        // Bind allowed Files
        while (e != null && e.hasMoreElements();); {
            // get the value of this input tag
            String inputName = (String); e.nextElement();;

            // get the content type
            String[] contentType = multiWrapper.getContentTypes(inputName);;

           
            File[] file = null;
            
            String[] fileName = null;
            try {
                // Get a File object for the uploaded File
                fileName = multiWrapper.getFileNames(inputName);;
                // get the name of the file from the input tag
                file = multiWrapper.getFiles(inputName);;
            } catch (RuntimeException e1); {
                log.info("Can't get file object from " + inputName + ", empty file field?");;
                continue;
            }

            if (file != null); {
                for (int i = 0; i < file.length; i++); {
                    log.info("file " + inputName + " " + contentType[i] + " " + fileName[i] + " " + file[i]);;
                }
            }

            // If it's null the upload failed
            if (file == null); {
                if (validation != null); {
                    validation.addFieldError(inputName, "Could not upload file(s);. Perhaps it is too large?");;
                }

                log.error("Error uploading: " + fileName);;
            } else {
                invocation.getInvocationContext();.getParameters();.put(inputName, file);;
                invocation.getInvocationContext();.getParameters();.put(inputName + "ContentType", contentType);;
                invocation.getInvocationContext();.getParameters();.put(inputName + "FileName", fileName);;
            }
        }

        // invoke action
        String result = invocation.invoke();;

        // cleanup
        e = multiWrapper.getFileParameterNames();;

        while (e != null && e.hasMoreElements();); {
            String inputValue = (String); e.nextElement();;
            File[] file = multiWrapper.getFiles(inputValue);;
            for (int i = 0; i < file.length; i++); {
                File f = file[i];
                log.info("removing file " + inputValue + " " + f);;

                if ((f != null); && f.isFile();); {
                    f.delete();;
                }
            }
        }

        return result;
    }
}
0 请登录后投票
   发表时间:2005-06-07  
换用pell做文件上传

在webwork.properties里面改
0 请登录后投票
   发表时间:2005-06-07  
scud 写道
换用pell做文件上传

在webwork.properties里面改


没用的,我本来就是用pell的,发现这个问题再换用cos都一样的。
0 请登录后投票
   发表时间:2005-06-07  
换apache file upload
0 请登录后投票
   发表时间:2005-06-08  
WebWork的这个upload拦截器确实忽略了这些大小的参数,不过可以仿照它的样子写一个还是蛮方便的:
import java.io.File;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.dispatcher.multipart.MultiPartRequestWrapper;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.ValidationAware;
import com.opensymphony.xwork.interceptor.Interceptor;

/**
 * a reusable FileUploadInterceptor, base on
 * com.opensymphony.webwork.interceptor.FileUploadInterceptor, for there are no
 * way to extend, so have to create this one. where [File Name] is the name
 * given to the file uploaded by the HTML form:
 * &lt;ul&gt;
 * &lt;li&gt;[File Name] : File - the actual File&lt;/li&gt;
 * &lt;li&gt;[File Name]ContentType : String - the content type of the file&lt;/li&gt;
 * &lt;li&gt;[File Name]FileName : String - the actual name of the file uploaded (not
 * the HTML name)&lt;/li&gt;
 * &lt;/ul&gt;
 * &lt;p/&gt;You can get access to these files by merely providing setters in your
 * action that coorespond to any of the three patterns above, such as
 * setDocument(File document), setDocumentContentType(String contentType), etc.
 * 
 * @author Quake Wang
 * @since 2004-8-24
 * @version $Revision: 1.2 $
 */
public class FileUploadInterceptor implements Interceptor {
    protected static final Log log = LogFactory.getLog(FileUploadInterceptor.class);

    protected String allowedTypes;
    protected String disallowedTypes;
    protected Long maximumSize;

    private MultiPartRequestWrapper multiWrapper;

    public void setAllowedTypes(String allowedTypes) {
        this.allowedTypes = allowedTypes;
    }

    public void setDisallowedTypes(String disallowedTypes) {
        this.disallowedTypes = disallowedTypes;
    }

    public void setMaximumSize(Long maximumSize) {
        this.maximumSize = maximumSize;
    }

    public void destroy() {

    }

    public void init() {

    }

    public String intercept(ActionInvocation invocation) throws Exception {
        if (!(ServletActionContext.getRequest() instanceof MultiPartRequestWrapper)) {
            log.debug("bypass " + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName());
            return invocation.invoke();
        }

        multiWrapper = (MultiPartRequestWrapper) ServletActionContext.getRequest();

        checkErrors(invocation);
        bindFiles(invocation);

        String result = invocation.invoke();

        cleanUpTempFiles();
        return result;
    }

    private void checkErrors(ActionInvocation invocation) {
        if (multiWrapper.hasErrors()) {
            Action action = invocation.getAction();
            Collection errors = multiWrapper.getErrors();
            Iterator i = errors.iterator();
            while (i.hasNext()) {
                processErrorMessage(action, (String) i.next());
            }
        }
    }

    protected void bindFiles(ActionInvocation invocation) {
        Enumeration e = multiWrapper.getFileParameterNames();
        if (e != null) {
            Action action = invocation.getAction();
            //Bind allowed Files
            while (e.hasMoreElements()) {
                String inputName = (String) e.nextElement();
                String[] contentType = multiWrapper.getContentTypes(inputName);
                String[] fileName = multiWrapper.getFileNames(inputName);
                File[] file = multiWrapper.getFiles(inputName);

                if (file != null) {
                    for (int i = 0; i &lt; file.length; i++) {
                        log.info("file " + inputName + " " + contentType[i] + " " + fileName[i] + " " + file[i]);
                    }
                }

                if (file == null) {
                    processErrorMessage(action, inputName, "Could not upload file(s). Perhaps it is too large?");
                } else if (acceptFile(file, contentType, inputName, action)) {
                    invocation.getInvocationContext().getParameters().put(inputName, file);
                    invocation.getInvocationContext().getParameters().put(inputName + "ContentType", contentType);
                    invocation.getInvocationContext().getParameters().put(inputName + "FileName", fileName);
                }
            }
        }
    }

    private void cleanUpTempFiles() {
        Enumeration e = multiWrapper.getFileParameterNames();
        if (e != null) {
            while (e.hasMoreElements()) {
                String inputValue = (String) e.nextElement();
                File[] file = multiWrapper.getFiles(inputValue);
                for (int i = 0; i &lt; file.length; i++) {
                    File f = file[i];
                    log.info("removing file " + inputValue + " " + f);

                    if ((f != null) && f.isFile()) {
                        f.delete();
                    }
                }
            }
        }
    }

    //overload this method to modify accept behaviour
    protected boolean acceptFile(File[] files, String[] contentTypes, String inputName, Action action) {
        for (int i = 0; i &lt; files.length; i++) {
            File file = files[i];
            String contentType = contentTypes[i];
            log.debug("checking" + inputName + " " + file.getName() + " " + file.length() + " " + contentType);
            if (maximumSize != null && maximumSize.longValue() &lt; file.length())
                processErrorMessage(action, inputName, "File size is too big: " + inputName + " " + file.getName() + " " + file.length());
            else if (allowedTypes != null && allowedTypes.indexOf(contentType) &lt; 0)
                processErrorMessage(action, inputName, "Content-Type not allowed: " + inputName + " " + file.getName() + " " + contentType);
            else if (disallowedTypes != null && disallowedTypes.indexOf(contentType) &gt;= 0)
                processErrorMessage(action, inputName, "Content-Type disallowed: " + inputName + " " + file.getName() + " " + contentType);
            else {
                log.debug("accepted");
                continue;
            }
            log.debug("not accepted");
            return false;
        }
        return true;
    }

    private void processErrorMessage(Action action, String errorMessage) {
        processErrorMessage(action, null, errorMessage);
    }

    //TODO i18n
    private void processErrorMessage(Action action, String field, String errorMessage) {
        if (action instanceof ValidationAware) {
            if (field != null) {
                ((ValidationAware) action).addFieldError(field, errorMessage);
            } else {
                ((ValidationAware) action).addActionError(errorMessage);
            }
        } else {
            log.error("[" + field + "] " + errorMessage);
        }

    }

}
0 请登录后投票
   发表时间:2005-06-08  
Quake Wang 写道
WebWork的这个upload拦截器确实忽略了这些大小的参数,不过可以仿照它的样子写一个还是蛮方便的:


这确实个方法,但不知道能不能像他代码暗示的那样,写个validator来做这些检查,大概得思路就是对action里的那个file field按照validation.xml里定义的allowedTypes,disallowedTypes,maximumSize在action层面上进行验证。

现在要做项目,没时间,等有时间可以自己写个看看。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics