JSF2.0虽然添加了很多新特性,但是还是没有官方的对上传的支持。直接使用
是不行的。因为multipart/form-data类型的request是解析不了的。
解决方法可以使用filter对request进行包装(原request似乎是不能更改的,所以借助包装),在解析request是可以借助apache的commons-fileupload组件。
Myfaces刚好给出了这个解决方案的实现:
MultipartFilter+MultipartRequestWrapper(Use commons-fileupload).
原来是打包在一个myfaces-extensions.jar中,现在找不到官方的下载,不过在Tomahawk包里可以找到(org.apache.myfaces.webapp.filter.*,MultipartFilter似乎都弄到ExtensionsFilter里了)。
个人觉得旧版的源代码挺参考价值的,贴出来分享下。
MultipartRequestWrapper:
- 1 /*
- 2 * Copyright 2004 The Apache Software Foundation.
- 3 *
- 4 * Licensed under the Apache License, Version 2.0 (the "License");
- 5 * you may not use this file except in compliance with the License.
- 6 * You may obtain a copy of the License at
- 7 *
- 8 * http://www.apache.org/licenses/LICENSE-2.0
- 9 *
- 10 * Unless required by applicable law or agreed to in writing, software
- 11 * distributed under the License is distributed on an "AS IS" BASIS,
- 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- 13 * See the License for the specific language governing permissions and
- 14 * limitations under the License.
- 15 */
- 16 package org.apache.myfaces.component.html.util;
- 17
- 18 import org.apache.commons.fileupload.*;
- 19 import org.apache.commons.logging.Log;
- 20 import org.apache.commons.logging.LogFactory;
- 21
- 22 import javax.servlet.http.HttpServletRequest ;
- 23 import javax.servlet.http.HttpServletRequestWrapper ;
- 24 import java.io.UnsupportedEncodingException ;
- 25 import java.util.*;
- 26
- 27 /**
- 28 * @author Sylvain Vieujot (latest modification by $Author: svieujot $)
- 29 * @version $Revision: 1.2 $ $Date: 2004/12/11 21:41:33 $
- 30 * $Log: MultipartRequestWrapper.java,v $
- 31 * Revision 1.2 2004/12/11 21:41:33 svieujot
- 32 * Add method to get the FileItems.
- 33 *
- 34 * Revision 1.1 2004/12/01 16:32:03 svieujot
- 35 * Convert the Multipart filter in an ExtensionsFilter that provides an additional facility to include resources in a page.
- 36 * Tested only with javascript resources right now, but should work fine with images too.
- 37 * Some work to do to include css resources.
- 38 * The popup component has been converted to use this new Filter.
- 39 *
- 40 * Revision 1.8 2004/11/16 16:25:52 mmarinschek
- 41 * new popup - component; not yet finished
- 42 *
- 43 * Revision 1.7 2004/10/13 11:50:57 matze
- 44 * renamed packages to org.apache
- 45 *
- 46 * Revision 1.6 2004/09/09 13:43:59 manolito
- 47 * query string parameters where missing in the parameter map
- 48 *
- 49 * Revision 1.5 2004/08/16 18:06:47 svieujot
- 50 * Another bug fix for bug #1001511. Patch submitted by Takashi Okamoto.
- 51 *
- 52 * Revision 1.4 2004/08/02 04:26:06 svieujot
- 53 * Fix for bug #1001511 : setHeaderEncoding
- 54 *
- 55 */
- 56 public class MultipartRequestWrapper
- 57 extends HttpServletRequestWrapper
- 58 {
- 59 private static Log log = LogFactory.getLog(MultipartRequestWrapper.class);
- 60
- 61 HttpServletRequest request = null;
- 62 HashMap parametersMap = null;
- 63 DiskFileUpload fileUpload = null;
- 64 HashMap fileItems = null;
- 65 int maxSize;
- 66 int thresholdSize;
- 67 String repositoryPath;
- 68
- 69 public MultipartRequestWrapper(HttpServletRequest request,
- 70 int maxSize, int thresholdSize,
- 71 String repositoryPath){
- 72 super( request );
- 73 this.request = request;
- 74 this.maxSize = maxSize;
- 75 this.thresholdSize = thresholdSize;
- 76 this.repositoryPath = repositoryPath;
- 77 }
- 78
- 79 private void parseRequest() {
- 80 fileUpload = new DiskFileUpload();
- 81 fileUpload.setFileItemFactory(new DefaultFileItemFactory());
- 82 fileUpload.setSizeMax(maxSize);
- 83
- 84 fileUpload.setSizeThreshold(thresholdSize);
- 85
- 86 if(repositoryPath != null && repositoryPath.trim().length()>0)
- 87 fileUpload.setRepositoryPath(repositoryPath);
- 88
- 89 String charset = request.getCharacterEncoding();
- 90 fileUpload.setHeaderEncoding(charset);
- 91
- 92
- 93 List requestParameters = null;
- 94 try{
- 95 requestParameters = fileUpload.parseRequest(request);
- 96 } catch (FileUploadBase.SizeLimitExceededException e) {
- 97
- 98 // TODO: find a way to notify the user about the fact that the uploaded file exceeded size limit
- 99
- 100 if(log.isInfoEnabled())
- 101 log.info("user tried to upload a file that exceeded file-size limitations.",e);
- 102
- 103 requestParameters = Collections.EMPTY_LIST;
- 104
- 105 }catch(FileUploadException fue){
- 106 log.error("Exception while uploading file.", fue);
- 107 requestParameters = Collections.EMPTY_LIST;
- 108 }
- 109
- 110 parametersMap = new HashMap( requestParameters.size() );
- 111 fileItems = new HashMap();
- 112
- 113 for (Iterator iter = requestParameters.iterator(); iter.hasNext(); ){
- 114 FileItem fileItem = (FileItem) iter.next();
- 115
- 116 if (fileItem.isFormField()) {
- 117 String name = fileItem.getFieldName();
- 118
- 119 // The following code avoids commons-fileupload charset problem.
- 120 // After fixing commons-fileupload, this code should be
- 121 //
- 122 // String value = fileItem.getString();
- 123 //
- 124 String value = null;
- 125 if ( charset == null) {
- 126 value = fileItem.getString();
- 127 } else {
- 128 try {
- 129 value = new String (fileItem.get(), charset);
- 130 } catch (UnsupportedEncodingException e){
- 131 value = fileItem.getString();
- 132 }
- 133 }
- 134
- 135 addTextParameter(name, value);
- 136 } else { // fileItem is a File
- 137 if (fileItem.getName() != null) {
- 138 fileItems.put(fileItem.getFieldName(), fileItem);
- 139 }
- 140 }
- 141 }
- 142
- 143 //Add the query string paramters
- 144 for (Iterator it = request.getParameterMap().entrySet().iterator(); it.hasNext(); )
- 145 {
- 146 Map.Entry entry = (Map.Entry)it.next();
- 147 String [] valuesArray = (String [])entry.getValue();
- 148 for (int i = 0; i < valuesArray.length; i++)
- 149 {
- 150 addTextParameter((String )entry.getKey(), valuesArray[i]);
- 151 }
- 152 }
- 153 }
- 154
- 155 private void addTextParameter(String name, String value){
- 156 if( ! parametersMap.containsKey( name ) ){
- 157 String [] valuesArray = {value};
- 158 parametersMap.put(name, valuesArray);
- 159 }else{
- 160 String [] storedValues = (String [])parametersMap.get( name );
- 161 int lengthSrc = storedValues.length;
- 162 String [] valuesArray = new String [lengthSrc+1];
- 163 System.arraycopy(storedValues, 0, valuesArray, 0, lengthSrc);
- 164 valuesArray[lengthSrc] = value;
- 165 parametersMap.put(name, valuesArray);
- 166 }
- 167 }
- 168
- 169 public Enumeration getParameterNames() {
- 170 if( parametersMap == null ) parseRequest();
- 171
- 172 return Collections.enumeration( parametersMap.keySet() );
- 173 }
- 174
- 175 public String getParameter(String name) {
- 176 if( parametersMap == null ) parseRequest();
- 177
- 178 String [] values = (String [])parametersMap.get( name );
- 179 if( values == null )
- 180 return null;
- 181 return values[0];
- 182 }
- 183
- 184 public String [] getParameterValues(String name) {
- 185 if( parametersMap == null ) parseRequest();
- 186
- 187 return (String [])parametersMap.get( name );
- 188 }
- 189
- 190 public Map getParameterMap() {
- 191 if( parametersMap == null ) parseRequest();
- 192
- 193 return parametersMap;
- 194 }
- 195
- 196 // Hook for the x:inputFileUpload tag.
- 197 public FileItem getFileItem(String fieldName) {
- 198 if( fileItems == null ) parseRequest();
- 199
- 200 return (FileItem) fileItems.get( fieldName );
- 201 }
- 202
- 203 /**
- 204 * Not used internaly by MyFaces, but provides a way to handle the uploaded files
- 205 * out of MyFaces.
- 206 */
- 207 public Map getFileItems(){
- 208 return fileItems;
- 209 }
- 210 }
MultipartFilter:
- 1 /*
- 2 * Copyright 2005 The Apache Software Foundation.
- 3 *
- 4 * Licensed under the Apache License, Version 2.0 (the "License");
- 5 * you may not use this file except in compliance with the License.
- 6 * You may obtain a copy of the License at
- 7 *
- 8 * http://www.apache.org/licenses/LICENSE-2.0
- 9 *
- 10 * Unless required by applicable law or agreed to in writing, software
- 11 * distributed under the License is distributed on an "AS IS" BASIS,
- 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- 13 * See the License for the specific language governing permissions and
- 14 * limitations under the License.
- 15 */
- 16 package org.apache.myfaces.component.html.util;
- 17
- 18 import java.io.IOException ;
- 19
- 20 import javax.servlet.Filter ;
- 21 import javax.servlet.FilterChain ;
- 22 import javax.servlet.FilterConfig ;
- 23 import javax.servlet.ServletException ;
- 24 import javax.servlet.ServletRequest ;
- 25 import javax.servlet.ServletResponse ;
- 26 import javax.servlet.http.HttpServletRequest ;
- 27 import javax.servlet.http.HttpServletResponse ;
- 28
- 29 import org.apache.commons.fileupload.FileUpload;
- 30
- 31
- 32 /**
- 33 * This filters is mandatory for the use of many components.
- 34 * It handles the Multipart requests (for file upload)
- 35 * It's used by the components that need javascript libraries
- 36 *
- 37 * @author Sylvain Vieujot (latest modification by $Author: oros $)
- 38 * @author Oliver Rossmueller
- 39 * @version $Revision: 1.1 $ $Date: 2005/03/20 23:16:08 $
- 40 */
- 41 public class MultipartFilter implements Filter
- 42 {
- 43
- 44 private int uploadMaxFileSize = 100 * 1024 * 1024; // 10 MB
- 45
- 46 private int uploadThresholdSize = 1 * 1024 * 1024; // 1 MB
- 47
- 48 private String uploadRepositoryPath = null; //standard temp directory
- 49
- 50
- 51 public void init(FilterConfig filterConfig)
- 52 {
- 53 uploadMaxFileSize = resolveSize(filterConfig.getInitParameter("uploadMaxFileSize"), uploadMaxFileSize);
- 54 uploadThresholdSize = resolveSize(filterConfig.getInitParameter("uploadThresholdSize"), uploadThresholdSize);
- 55 uploadRepositoryPath = filterConfig.getInitParameter("uploadRepositoryPath");
- 56 }
- 57
- 58
- 59 private int resolveSize(String param, int defaultValue)
- 60 {
- 61 int numberParam = defaultValue;
- 62
- 63 if (param != null)
- 64 {
- 65 param = param.toLowerCase();
- 66 int factor = 1;
- 67 String number = param;
- 68
- 69 if (param.endsWith("g"))
- 70 {
- 71 factor = 1024 * 1024 * 1024;
- 72 number = param.substring(0, param.length() - 1);
- 73 } else if (param.endsWith("m"))
- 74 {
- 75 factor = 1024 * 1024;
- 76 number = param.substring(0, param.length() - 1);
- 77 } else if (param.endsWith("k"))
- 78 {
- 79 factor = 1024;
- 80 number = param.substring(0, param.length() - 1);
- 81 }
- 82
- 83 numberParam = Integer.parseInt(number) * factor;
- 84 }
- 85 return numberParam;
- 86 }
- 87
- 88
- 89 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException , ServletException
- 90 {
- 91 if (!(response instanceof HttpServletResponse ))
- 92 {
- 93 chain.doFilter(request, response);
- 94 return;
- 95 }
- 96
- 97 HttpServletRequest httpRequest = (HttpServletRequest ) request;
- 98
- 99 // For multipart/form-data requests
- 100 if (FileUpload.isMultipartContent(httpRequest))
- 101 {
- 102 chain.doFilter(new MultipartRequestWrapper(httpRequest, uploadMaxFileSize, uploadThresholdSize, uploadRepositoryPath), response);
- 103 } else
- 104 {
- 105 chain.doFilter(request, response);
- 106 }
- 107 }
- 108
- 109
- 110 public void destroy()
- 111 {
- 112 // NoOp
- 113 }
- 114 }