重写struts2文件上传处理类
1.struts文件配置
<!--文件大小限制-->
<constant name="struts.multipart.maxSize" value="1073741824" />
<!--文件上传临时目录-->
<constant name="struts.multipart.saveDir" value="tmp"></constant>
<!--处理类声明-->
<bean
type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name="perfmpr"
/>
<!--处理类定义-->
<constant name="struts.multipart.handler" value="perfmpr" />
2.编写处理类 继承JakartaMultiPartRequest
package com.huawei.devportal.common;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;
import com.huawei.portalone.common.log.Log;
import com.huawei.portalone.common.log.LogManager;
/**
* 在原有JakartaMultiPartRequest处理类的基础上做了调整,解决在大并发下文件上传,
* 导致生成大量临时文件没有清理问题
*/
public class PerfMultiPartRequest extends JakartaMultiPartRequest
{
private static final Log log = LogManager.getDebugLog();
/**
* 解析时在原有JakartaMultiPartRequest处理类的基础上做了两个调整,原有parse函数版权归apache的struts所有。
* 1.在处理附件时设置1M的内存,用于临时存放文件,避免每次都写文件。
* 原先struts:fac.setSizeThreshold(0); //原先原码里面还标明了直接写文件,但是不知道为啥这样做,不知道哪位达人清楚原因。
* 新调整为:fac.setSizeThreshold(1024 * 1024);
* 2.对于formfield的项,解析完成就删除,不用遗留到最后用gc删除。遗留延迟删除会导致生成大量垃圾小文件。
* 新增:item.delete();
*
*
* @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();
fac.setSizeThreshold(1024 * 1024);
if (saveDir != null)
{
fac.setRepository(new File(saveDir));
}
// Parse the request
ServletFileUpload upload = new ServletFileUpload(fac);
upload.setSizeMax(maxSize);
servletRequest.setAttribute("maxSize", maxSize);
List<FileItem> items = null;
try
{
items = (List<FileItem>)upload.parseRequest(createRequestContext(servletRequest));
for (Object item1 : items)
{
FileItem item = (FileItem) item1;
String itemFieldName = item.getFieldName();
if (log.isDebugEnabled())
{
log.debug("Found item " + itemFieldName);
}
if (item.isFormField())
{
log.debug("Item is a normal form field");
List<String> values = params.get(itemFieldName);
if (null == values)
{
values = new ArrayList<String>();
}
String charset = servletRequest.getCharacterEncoding();
if (null == charset)
{
values.add(item.getString());
}
else
{
values.add(item.getString(charset));
}
params.put(itemFieldName, values);
item.delete();
}
else
{
log.debug("Item is a file upload");
// Skip file uploads that don't have a file name - meaning that no file was selected.
if (null == item.getName()
|| item.getName().trim().length() < 1)
{
log.debug("No file has been uploaded for the field: "
+ itemFieldName);
continue;
}
List<FileItem> values = files.get(itemFieldName);
if (null == values)
{
values = new ArrayList<FileItem>();
}
if (item.isInMemory())
{
try
{
item.write(((DiskFileItem)item).getStoreLocation());
}
catch (Exception e)
{
log.warn("Unable to write item", e);
errors.add(e.getMessage());
}
}
values.add(item);
files.put(itemFieldName, values);
}
}
}
catch (FileUploadException e)
{
log.warn("Unable to parse request", e);
errors.add(e.getMessage());
}
}
/**
* 由于parse需要此函数,但是JakartaMultiPartRequest类不允许子类访问,所以
* 这里又重新定义一遍。此方法沿用JakartaMultiPartRequest类的createRequestContext类处理,
* 没有做任何调整
*
* @param req the request.
* @return a new request context.
*/
private RequestContext createRequestContext(final HttpServletRequest req)
{
return new RequestContext()
{
public String getCharacterEncoding()
{
return req.getCharacterEncoding();
}
public String getContentType()
{
return req.getContentType();
}
public int getContentLength()
{
return req.getContentLength();
}
public InputStream getInputStream() throws IOException
{
InputStream inputStream = req.getInputStream();
if (inputStream == null)
{
throw new IOException("Missing content in the request");
}
return req.getInputStream();
}
};
}
}
/**
public void preExecute() throws DVException
{
if (httpServletRequest instanceof MultiPartRequestWrapper)
{
MultiPartRequestWrapper requestWrapper = (MultiPartRequestWrapper) httpServletRequest;
if (requestWrapper.hasErrors())
{
Collection<String> errors = requestWrapper.getErrors();
if (errors != null && !errors.isEmpty())
{
Iterator iterator = errors.iterator();
long maxSize = 0;
if (requestWrapper.getAttribute("maxSize") != null)
{
maxSize = Long.parseLong(requestWrapper.getAttribute("maxSize")
.toString());
maxSize = maxSize / 1024 / 1024;
}
while (iterator.hasNext())
{
String errorMess = (String) iterator.next();
log.warn(errorMess);
throw new DVException(
ErrorNumber.Resource.RESOURCE_ADD_FILE_SIZE,
new String[] {maxSize + ""});
}
}
return;
}
Enumeration<String> parameterNames = requestWrapper.getFileParameterNames();
while (parameterNames.hasMoreElements())
{
@SuppressWarnings("unused")
String paramterName = parameterNames.nextElement();
File[] files = requestWrapper.getFiles(paramterName);
if (null == files || files.length == 0)
{
continue;
}
else if (files.length == 1)
{
FileBean fileBean = new FileBean();
fileBean.setAbsolutePath(files[0].getAbsolutePath());
fileBean.setFileSize(files[0].length());
fileBean.setFilename(requestWrapper.getFileNames(paramterName)[0]);
this.fileMap.put(paramterName, fileBean);
}
else
{
ArrayList<FileBean> list = new ArrayList();
for (int i = 0; i < files.length; i++)
{
File file = files[i];
FileBean fileBean = new FileBean();
fileBean.setAbsolutePath(file.getAbsolutePath());
fileBean.setFileSize(file.length());
fileBean.setFilename(requestWrapper.getFileNames(paramterName)[i]);
list.add(fileBean);
}
this.fileMap.put(paramterName, list);
}
}
}
}
**/