Jealous of Webwork2's File Upload Interceptor? If you are done with Spring Framework Integration with Webwork, with a little effort you can enjoy the same convenience with the help of Spring's AOP framework.
First, we introduce a new interface for our file upload interceptor to identify and inject the values appropriately.
So, we have UploadFileAware interface:
package webwork.ext.spring;
import java.io.File;
public interface UploadFileAware
{
public void setFile(File file);
public void setFilename(String filename);
}
Note: Current codes in Webwork1's CVS contains a new WebworkMultipartRequest parser (internal) which returns uploaded files as temporary files. If you will be using cos or pell's MultipartRequest parser you can omit the setFilename method.
Of course, if your Webwork Action will need to process multiple uploaded files you may have a MultipleUploadFileAware interface which injects an array of Files and Filenames.
Next we have _FileUploadInterceptor_. Of course you can override the values and types of file accepted through configurations at Spring's applicationContext.xml.
package webwork.ext.spring;
import java.io.File;
import java.util.Enumeration;
import webwork.action.ActionContext;
import webwork.config.Configuration;
import webwork.multipart.MultiPartRequestWrapper;
import webwork.action.ServletActionContext;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class FileUploadInterceptor implements MethodInterceptor
{
private static final String ALL_FILES_ACCEPTED = "*";
private static final long DEFAULT_MAX_FILE_SIZE =
Long.parseLong(Configuration.getString("webwork.multipart.maxSize"));
private String acceptedTypes = ALL_FILES_ACCEPTED;
private long maxFileSize = DEFAULT_MAX_FILE_SIZE;
private final Log logger = LogFactory.getLog(getClass());
public void setMaxFileSize(long maxFileSize)
{
this.maxFileSize = maxFileSize;
}
public void setAcceptedTypes(String acceptedTypes)
{
this.acceptedTypes = acceptedTypes;
}
public Object invoke(MethodInvocation methodInvocation) throws Throwable
{
if(methodInvocation.getThis() instanceof UploadFileAware)
{
if(logger.isDebugEnabled()) logger.debug("Intercepting call: " +
methodInvocation.getMethod().getDeclaringClass() + ":: " +
methodInvocation.getMethod().getName());
if (!(ServletActionContext.getRequest() instanceof
MultiPartRequestWrapper))
{
return methodInvocation.proceed();
}
MultiPartRequestWrapper multiWrapper =
(MultiPartRequestWrapper) ServletActionContext.getRequest();
Enumeration e = multiWrapper.getFileNames();
while(e.hasMoreElements())
{
String inputName = (String) e.nextElement();
String contentType = multiWrapper.getContentType(inputName);
String fileName = multiWrapper.getFilesystemName(inputName);
File file = multiWrapper.getFile(inputName);
if (file != null)
{
logger.info("file " + inputName + " " + contentType
+ " " + fileName + " " + file);
if (acceptFile(file, contentType, inputName))
{
UploadFileAware underlyingAction =
(UploadFileAware)methodInvocation.getThis();
underlyingAction.setFile(file);
underlyingAction.setFilename(fileName);
}
}
}
Object retVal = methodInvocation.proceed();
/*e = multiWrapper.getFileNames();
while (e.hasMoreElements())
{
String inputValue = (String) e.nextElement();
File file = multiWrapper.getFile(inputValue);
logger.info("removing file " + inputValue + " " + file);
if (file != null && file.isFile()) file.delete();
}*/
return retVal;
}
if(logger.isDebugEnabled())
logger.debug(methodInvocation.getMethod().getDeclaringClass()
+ ":: " + methodInvocation.getMethod().getName() + " not intercepted");
return methodInvocation.proceed();
}
private boolean acceptFile(File file, String contentType, String inputName)
{
if(file.length() > maxFileSize)
{
if(logger.isDebugEnabled())
logger.debug("Not accepted: File size > max allowed size");
return false;
}
else
{
if(acceptedTypes.equals(ALL_FILES_ACCEPTED))
{
if(logger.isDebugEnabled()) logger.debug("accepted");
return true;
}
else
{
if(acceptedTypes.indexOf(contentType) < 0)
{
if(logger.isDebugEnabled()) logger.debug("accepted: " +
contentType);
return true;
}
if(logger.isDebugEnabled()) logger.debug("not accepted: " +
contentType);
return false;
}
}
}
}
Again, this interceptor process single uploaded file only. However you can modify it to process multiple uploaded files with a little effort.
In the Action using the file upload interceptor just need to implement the UploadFileAware interface:
....
import java.io.File;
import webwork.action.ActionSupport;
import webwork.ext.spring.UploadFileAware;
public class MyAction extends ActionSupport implements UploadFileAware
{
private File uploadedFile;
private String uploadedFilename;
public void setFile(File file)
{
this.uploadedFile = file;
}
public void setFilename(String filename)
{
this.uploadedFilename = filename;
}
public String execute()
{
....
uploadedFile.renameTo(new File(ApplicationSettings.DEFAULT_IMAGE_DIRECTORY
+ File.separator + uploadedFilename));
....
}
....
}
Last step we just need to configure the collaborations between the interceptor and the WW Action on _applicationContext.xml_. Here we follow the way we did at Spring Framework Integration.
<bean id="fileUploadInterceptor"
class="webwork.ext.spring.FileUploadInterceptor" />
<bean id="fileUploadInterceptorAdvice"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<ref local="fileUploadInterceptor"/>
</property>
<property name="mappedName">
<value>execute</value>
</property>
</bean>
<bean id="proxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass"><value>true</value></property>
<property name="interceptorNames">
<list>
<value>fileUploadInterceptorAdvice</value>
</list>
</property>
<property name="beanNames">
<list>
<value>MyAction</value>
</list>
</property>
</bean>
<bean id="MyAction" class="MyAction" singleton="false" />
Now you can free your Actions from doing the dirty laundry of processing uploaded files!
If we want to upload file to another directory/folder instead of temp, how can we do that?
Thanks!