您的位置:首页 > 编程语言 > Java开发

struts2上传文件的File属性如何装载

2009-01-12 17:15 316 查看
struts2的文件上传很容易,特别是对上传文件的2进制流解析,操作很透明。只要action有个File类型的属性给setter方法就直接把2进制文件给封装成File了。

开始的时候,我是打算在在servlet中手动解析的,后发现太繁琐要判断2进制文件流的开始和结束还有及加载其中的表单域,还要考率超大文件的内存溢出问题。TMD真不爽。后来打算借鉴一下struts2的代码。但是,struts2怎么把2进制文件变成了File了? File是通常是关联到本地操作系统上的文件,上传的文件是封装在request对象中的,怎么能封装成本地的文件,难道是先传到临时目录在写到指定目录,但考虑到性能问题应该是边传边写的啊。

不知道很不爽啊,感觉就是gf背着你和别的帅哥出去约会一样,并且约会的人是struts2团队的一个老外,想想就更不爽了。于是我就是开始看源码。struts2的上传是用拦截器实现的,打开struts2-core.jar包很容易找到org.apache.struts2.interceptor
这个包,以后瞅瞅一眼就看到FileUploadInterceptor.class这个文件了。打开相应的源码:

/*

*.省略导入文件

*/

public String intercept(ActionInvocation invocation) throws Exception {

ActionContext ac = invocation.getInvocationContext();

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()}, ActionContext.getContext().getLocale()));

}

return invocation.invoke();

}

final Object action = invocation.getAction();

ValidationAware validation = null;

if (action instanceof ValidationAware) {

validation = (ValidationAware) action;

}

MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;

if (multiWrapper.hasErrors()) {

for (Iterator errorIter = multiWrapper.getErrors().iterator(); errorIter.hasNext();) {

String error = (String) errorIter.next();

if (validation != null) {

validation.addActionError(error);

}

LOG.error(error);

}

}

Map parameters = ac.getParameters();

// 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了,看来是multiWrapper的问题

File[] files = multiWrapper.getFiles(inputName);

if (files != null) {

for (int index = 0; index < files.length; index++) {

if (acceptFile(files[index], contentType[index], inputName, validation, ac.getLocale())) {

parameters.put(inputName, files);

parameters.put(inputName + "ContentType", contentType);

parameters.put(inputName + "FileName", fileName);

}

}

}

} else {

LOG.error(getTextMessage("struts.messages.invalid.file", new Object[]{inputName}, ActionContext.getContext().getLocale()));

}

} else {

LOG.error(getTextMessage("struts.messages.invalid.content.type", new Object[]{inputName}, ActionContext.getContext().getLocale()));

}

}

// invoke action

String result = invocation.invoke();

// cleanup

fileParameterNames = multiWrapper.getFileParameterNames();

while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {

String inputValue = (String) fileParameterNames.nextElement();

File[] file = multiWrapper.getFiles(inputValue);

for (int index = 0; index < file.length; index++) {

File currentFile = file[index];

if(LOG.isInfoEnabled()) {

LOG.info(getTextMessage("struts.messages.removing.file", new Object[]{inputValue, currentFile}, ActionContext.getContext().getLocale()));

}

if ((currentFile != null) && currentFile.isFile()) {

currentFile.delete();

}

}

}

return result;

}

/*

*省略一些代码

*/

}

multiWrapper是MultiPartRequestWrapper是这个类型的所以继续产看MultiPartRequestWrapper的代码

public class MultiPartRequestWrapper extends StrutsRequestWrapper {

protected static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestWrapper.class);

Collection<String> errors;

// MultiPartRequest 是得到file的关键

MultiPartRequest multi;

public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir) {

super(request);

multi = multiPartRequest;

try {

multi.parse(request, saveDir);

for (Object o : multi.getErrors()) {

String error = (String) o;

addError(error);

}

} catch (IOException e) {

addError("Cannot parse request: "+e.toString());

}

}

public File[] getFiles(String fieldName) {

if (multi == null) {

return null;

}

//通过multi得到File的

return multi.getFile(fieldName);

}

}

综上我开始查看MultiPartRequest类,但是发现他是个接口,nnd没办法 只有找他的实现类,结果发现是JakartaMultiPartRequest,名字帅的很啊。那就看代码:

public class JakartaMultiPartRequest implements MultiPartRequest {

static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);

// maps parameter name -> List of FileItem objects

private Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();

// maps parameter name -> List of param values

private Map<String,List<String>> params = new HashMap<String,List<String>>();

// any errors while processing this request

private List<String> errors = new ArrayList<String>();

private long maxSize;

@Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)

public void setMaxSize(String maxSize) {

this.maxSize = Long.parseLong(maxSize);

}

//主要就是这个方法解析了request并封装成了File类型

很明显使用了commons-fileupload.jar的框架

public void parse(HttpServletRequest servletRequest, String saveDir)

throws IOException {

DiskFileItemFactory fac = new DiskFileItemFactory();

// Make sure that the data is written to file

//控制上传文件大小的阀值设置成了0,这就会直接写到临时文件去了

fac.setSizeThreshold(0);

if (saveDir != null) {

//设置临时目录

fac.setRepository(new File(saveDir));

}

// Parse the request

try {

ServletFileUpload upload = new ServletFileUpload(fac);

upload.setSizeMax(maxSize);

List items = upload.parseRequest(createRequestContext(servletRequest));

for (Object item1 : items) {

FileItem item = (FileItem) item1;

if (LOG.isDebugEnabled()) LOG.debug("Found item " + item.getFieldName());

if (item.isFormField()) {

LOG.debug("Item is a normal form field");

List<String> values;

if (params.get(item.getFieldName()) != null) {

values = params.get(item.getFieldName());

} else {

values = new ArrayList<String>();

}

// note: see http://jira.opensymphony.com/browse/WW-633
// basically, in some cases the charset may be null, so

// we're just going to try to "other" method (no idea if this

// will work)

String charset = servletRequest.getCharacterEncoding();

if (charset != null) {

values.add(item.getString(charset));

} else {

values.add(item.getString());

}

params.put(item.getFieldName(), values);

} 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 (item.getName() == null || item.getName().trim().length() < 1) {

LOG.debug("No file has been uploaded for the field: " + item.getFieldName());

continue;

}

List<FileItem> values;

if (files.get(item.getFieldName()) != null) {

values = files.get(item.getFieldName());

} else {

values = new ArrayList<FileItem>();

}

values.add(item);

//把解析出来的文件都放到这里

files.put(item.getFieldName(), values);

}

}

} catch (FileUploadException e) {

LOG.error("Unable to parse request", e);

errors.add(e.getMessage());

}

}

//根据文件名返回File数组

public File[] getFile(String fieldName) {

List items = (List) files.get(fieldName);

if (items == null) {

return null;

}

List<File> fileList = new ArrayList<File>(items.size());

for (int i = 0; i < items.size(); i++) {

DiskFileItem fileItem = (DiskFileItem) items.get(i);

fileList.add(fileItem.getStoreLocation());

}

return (File[]) fileList.toArray(new File[fileList.size()]);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: