/** $Id: JakartaMultiPartRequest.java 1384107 2012-09-12 20:14:23Z lukaszlenart $
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*http://www.apache.org/licenses/LICENSE-2.0*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.*/
packagecom.clzhang.struts2.demo12;importcom.opensymphony.xwork2.LocaleProvider;importcom.opensymphony.xwork2.inject.Inject;importcom.opensymphony.xwork2.util.LocalizedTextUtil;importcom.opensymphony.xwork2.util.logging.Logger;importcom.opensymphony.xwork2.util.logging.LoggerFactory;importorg.apache.commons.fileupload.FileItem;importorg.apache.commons.fileupload.FileUploadBase;importorg.apache.commons.fileupload.FileUploadException;importorg.apache.commons.fileupload.RequestContext;importorg.apache.commons.fileupload.disk.DiskFileItem;importorg.apache.commons.fileupload.disk.DiskFileItemFactory;importorg.apache.commons.fileupload.servlet.ServletFileUpload;importorg.apache.struts2.StrutsConstants;importjavax.servlet.http.HttpServletRequest;importjava.io.File;importjava.io.IOException;importjava.io.InputStream;importjava.io.UnsupportedEncodingException;importjava.util.ArrayList;importjava.util.Collections;importjava.util.Enumeration;importjava.util.HashMap;importjava.util.List;importjava.util.Locale;importjava.util.Map;importjava.util.Set;importorg.apache.struts2.dispatcher.multipart.MultiPartRequest;/*** Multipart form data request adapter for Jakarta Commons Fileupload package.*/
public class MyJakartaMultiPartRequest implementsMultiPartRequest {static final Logger LOG = LoggerFactory.getLogger(MyJakartaMultiPartRequest.class);//maps parameter name -> List of FileItem objects
protected Map> files = new HashMap>();//maps parameter name -> List of param values
protected Map> params = new HashMap>();//any errors while processing this request
protected List errors = new ArrayList();protected longmaxSize;private Locale defaultLocale =Locale.ENGLISH;
@Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)public voidsetMaxSize(String maxSize) {this.maxSize =Long.parseLong(maxSize);
}
@Injectpublic voidsetLocaleProvider(LocaleProvider provider) {
defaultLocale=provider.getLocale();
}/*** Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
* multipart classes (see class description).
*
*@paramsaveDir the directory to save off the file
*@paramrequest the request containing the multipart
*@throwsjava.io.IOException is thrown if encoding fails.*/
public void parse(HttpServletRequest request, String saveDir) throwsIOException {try{
setLocale(request);
processUpload(request, saveDir);
}catch(FileUploadBase.SizeLimitExceededException e) {if(LOG.isWarnEnabled()) {
LOG.warn("Request exceeded size limit!", e);
}
String errorMessage= buildErrorMessage(e, newObject[]{e.getPermittedSize(), e.getActualSize()});if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
}catch(Exception e) {if(LOG.isWarnEnabled()) {
LOG.warn("Unable to parse request", e);
}
String errorMessage= buildErrorMessage(e, newObject[]{});if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
}
}protected voidsetLocale(HttpServletRequest request) {if (defaultLocale == null) {
defaultLocale=request.getLocale();
}
}protectedString buildErrorMessage(Throwable e, Object[] args) {
String errorKey= "struts.messages.upload.error." +e.getClass().getSimpleName();if(LOG.isDebugEnabled()) {
LOG.debug("Preparing error message for key: [#0]", errorKey);
}return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
}private void processUpload(HttpServletRequest request, String saveDir) throwsFileUploadException, UnsupportedEncodingException {for(FileItem item : parseRequest(request, saveDir)) {if(LOG.isDebugEnabled()) {
LOG.debug("Found item " +item.getFieldName());
}if(item.isFormField()) {
processNormalFormField(item, request.getCharacterEncoding());
}else{
processFileField(item);
}
}
}private voidprocessFileField(FileItem item) {if(LOG.isDebugEnabled()) {
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());return;
}
Listvalues;if (files.get(item.getFieldName()) != null) {
values=files.get(item.getFieldName());
}else{
values= new ArrayList();
}
values.add(item);
files.put(item.getFieldName(), values);
}private void processNormalFormField(FileItem item, String charset) throwsUnsupportedEncodingException {if(LOG.isDebugEnabled()) {
LOG.debug("Item is a normal form field");
}
Listvalues;if (params.get(item.getFieldName()) != null) {
values=params.get(item.getFieldName());
}else{
values= new ArrayList();
}//note: seehttp://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)
if (charset != null) {
values.add(item.getString(charset));
}else{
values.add(item.getString());
}
params.put(item.getFieldName(), values);
item.delete();
}private List parseRequest(HttpServletRequest servletRequest, String saveDir) throwsFileUploadException {
DiskFileItemFactory fac=createDiskFileItemFactory(saveDir);
ServletFileUpload upload= newServletFileUpload(fac);
upload.setProgressListener(new FileUploadListener(servletRequest));//设置上传进度的监听
upload.setSizeMax(maxSize);returnupload.parseRequest(createRequestContext(servletRequest));
}privateDiskFileItemFactory createDiskFileItemFactory(String saveDir) {
DiskFileItemFactory fac= newDiskFileItemFactory();//Make sure that the data is written to file
fac.setSizeThreshold(0);if (saveDir != null) {
fac.setRepository(newFile(saveDir));
}returnfac;
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileParameterNames()*/
public EnumerationgetFileParameterNames() {returnCollections.enumeration(files.keySet());
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)*/
publicString[] getContentType(String fieldName) {
List items =files.get(fieldName);if (items == null) {return null;
}
List contentTypes = new ArrayList(items.size());for(FileItem fileItem : items) {
contentTypes.add(fileItem.getContentType());
}return contentTypes.toArray(newString[contentTypes.size()]);
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)*/
publicFile[] getFile(String fieldName) {
List items =files.get(fieldName);if (items == null) {return null;
}
List fileList = new ArrayList(items.size());for(FileItem fileItem : items) {
File storeLocation=((DiskFileItem) fileItem).getStoreLocation();if (fileItem.isInMemory() && storeLocation != null && !storeLocation.exists()) {try{
storeLocation.createNewFile();
}catch(IOException e) {if(LOG.isErrorEnabled()) {
LOG.error("Cannot write uploaded empty file to disk: " +storeLocation.getAbsolutePath(), e);
}
}
}
fileList.add(storeLocation);
}return fileList.toArray(newFile[fileList.size()]);
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(java.lang.String)*/
publicString[] getFileNames(String fieldName) {
List items =files.get(fieldName);if (items == null) {return null;
}
List fileNames = new ArrayList(items.size());for(FileItem fileItem : items) {
fileNames.add(getCanonicalName(fileItem.getName()));
}return fileNames.toArray(newString[fileNames.size()]);
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)*/
publicString[] getFilesystemName(String fieldName) {
List items =files.get(fieldName);if (items == null) {return null;
}
List fileNames = new ArrayList(items.size());for(FileItem fileItem : items) {
fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
}return fileNames.toArray(newString[fileNames.size()]);
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)*/
publicString getParameter(String name) {
List v =params.get(name);if (v != null && v.size() > 0) {return v.get(0);
}return null;
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterNames()*/
public EnumerationgetParameterNames() {returnCollections.enumeration(params.keySet());
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterValues(java.lang.String)*/
publicString[] getParameterValues(String name) {
List v =params.get(name);if (v != null && v.size() > 0) {return v.toArray(newString[v.size()]);
}return null;
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()*/
public ListgetErrors() {returnerrors;
}/*** Returns the canonical name of the given file.
*
*@paramfilename the given file
*@returnthe canonical name of the given file*/
privateString getCanonicalName(String filename) {int forwardSlash = filename.lastIndexOf("/");int backwardSlash = filename.lastIndexOf("\\");if (forwardSlash != -1 && forwardSlash >backwardSlash) {
filename= filename.substring(forwardSlash + 1, filename.length());
}else if (backwardSlash != -1 && backwardSlash >=forwardSlash) {
filename= filename.substring(backwardSlash + 1, filename.length());
}returnfilename;
}/*** Creates a RequestContext needed by Jakarta Commons Upload.
*
*@paramreq the request.
*@returna new request context.*/
private RequestContext createRequestContext(finalHttpServletRequest req) {return newRequestContext() {publicString getCharacterEncoding() {returnreq.getCharacterEncoding();
}publicString getContentType() {returnreq.getContentType();
}public intgetContentLength() {returnreq.getContentLength();
}public InputStream getInputStream() throwsIOException {
InputStream in=req.getInputStream();if (in == null) {throw new IOException("Missing content in the request");
}returnreq.getInputStream();
}
};
}/*(non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#cleanUp()*/
public voidcleanUp() {
Set names =files.keySet();for(String name : names) {
List items =files.get(name);for(FileItem item : items) {if(LOG.isDebugEnabled()) {
String msg= LocalizedTextUtil.findText(this.getClass(), "struts.messages.removing.file",
Locale.ENGLISH,"no.message.found", newObject[]{name, item});
LOG.debug(msg);
}if (!item.isInMemory()) {
item.delete();
}
}
}
}
}