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

      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这个文件了。打开相应的源码:
  1. /*
  2.  *.省略导入文件
  3.  */
  4.  public String intercept(ActionInvocation invocation) throws Exception {
  5.         ActionContext ac = invocation.getInvocationContext();
  6.         HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
  7.         if (!(request instanceof MultiPartRequestWrapper)) {
  8.             if (LOG.isDebugEnabled()) {
  9.                 ActionProxy proxy = invocation.getProxy();
  10.                 LOG.debug(getTextMessage("struts.messages.bypass.request"new Object[]{proxy.getNamespace(), proxy.getActionName()}, ActionContext.getContext().getLocale()));
  11.             }
  12.             return invocation.invoke();
  13.         }
  14.         final Object action = invocation.getAction();
  15.         ValidationAware validation = null;
  16.         if (action instanceof ValidationAware) {
  17.             validation = (ValidationAware) action;
  18.         }
  19.         MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
  20.         if (multiWrapper.hasErrors()) {
  21.             for (Iterator errorIter = multiWrapper.getErrors().iterator(); errorIter.hasNext();) {
  22.                 String error = (String) errorIter.next();
  23.                 if (validation != null) {
  24.                     validation.addActionError(error);
  25.                 }
  26.                 LOG.error(error);
  27.             }
  28.         }
  29.         Map parameters = ac.getParameters();
  30.         // Bind allowed Files
  31.         Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
  32.         while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
  33.             // get the value of this input tag
  34.             String inputName = (String) fileParameterNames.nextElement();
  35.             // get the content type
  36.             String[] contentType = multiWrapper.getContentTypes(inputName);
  37.             if (isNonEmpty(contentType)) {
  38.                 // get the name of the file from the input tag
  39.                 String[] fileName = multiWrapper.getFileNames(inputName);
  40.                 if (isNonEmpty(fileName)) {
  41.                     // Get a File object for the uploaded File
  42.                     //这里这么就一下得到file了,看来是multiWrapper的问题
  43.                     File[] files = multiWrapper.getFiles(inputName);
  44.                     if (files != null) {
  45.                         for (int index = 0; index < files.length; index++) {
  46.                             if (acceptFile(files[index], contentType[index], inputName, validation, ac.getLocale())) {
  47.                                 parameters.put(inputName, files);
  48.                                 parameters.put(inputName + "ContentType", contentType);
  49.                                 parameters.put(inputName + "FileName", fileName);
  50.                             }
  51.                         }
  52.                     }
  53.                 } else {
  54.                     LOG.error(getTextMessage("struts.messages.invalid.file"new Object[]{inputName}, ActionContext.getContext().getLocale()));
  55.                 }
  56.             } else {
  57.                 LOG.error(getTextMessage("struts.messages.invalid.content.type"new Object[]{inputName}, ActionContext.getContext().getLocale()));
  58.             }
  59.         }
  60.         // invoke action
  61.         String result = invocation.invoke();
  62.         // cleanup
  63.         fileParameterNames = multiWrapper.getFileParameterNames();
  64.         while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
  65.             String inputValue = (String) fileParameterNames.nextElement();
  66.             File[] file = multiWrapper.getFiles(inputValue);
  67.             for (int index = 0; index < file.length; index++) {
  68.                 File currentFile = file[index];
  69.                 if(LOG.isInfoEnabled()) {
  70.                     LOG.info(getTextMessage("struts.messages.removing.file"new Object[]{inputValue, currentFile}, ActionContext.getContext().getLocale()));
  71.                 }
  72.                 if ((currentFile != null) && currentFile.isFile()) {
  73.                     currentFile.delete();
  74.                 }
  75.             }
  76.         }
  77.         return result;
  78.     }
  79.   /*
  80.    *省略一些代码
  81.    */
  82. }
multiWrapper是MultiPartRequestWrapper是这个类型的所以继续产看MultiPartRequestWrapper的代码
  1. public class MultiPartRequestWrapper extends StrutsRequestWrapper {
  2.     protected static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestWrapper.class);
  3.     Collection<String> errors;
  4.     // MultiPartRequest 是得到file的关键 
  5.     MultiPartRequest multi;
  6. public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir) {
  7.         super(request);
  8.         
  9.         multi = multiPartRequest;
  10.         try {
  11.             multi.parse(request, saveDir);
  12.             for (Object o : multi.getErrors()) {
  13.                 String error = (String) o;
  14.                 addError(error);
  15.             }
  16.         } catch (IOException e) {
  17.             addError("Cannot parse request: "+e.toString());
  18.         } 
  19.     }
  20.   public File[] getFiles(String fieldName) {
  21.         if (multi == null) {
  22.             return null;
  23.         }
  24.         //通过multi得到File的
  25.         return multi.getFile(fieldName);
  26.     }
  27. }
综上我开始查看MultiPartRequest类,但是发现他是个接口,nnd没办法 只有找他的实现类,结果发现是JakartaMultiPartRequest,名字帅的很啊。那就看代码:
  1. public class JakartaMultiPartRequest implements MultiPartRequest {
  2.     
  3.     static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);
  4.     
  5.     // maps parameter name -> List of FileItem objects
  6.     private Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
  7.     // maps parameter name -> List of param values
  8.     private Map<String,List<String>> params = new HashMap<String,List<String>>();
  9.     // any errors while processing this request
  10.     private List<String> errors = new ArrayList<String>();
  11.     
  12.     private long maxSize;
  13.     
  14.     @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
  15.     public void setMaxSize(String maxSize) {
  16.         this.maxSize = Long.parseLong(maxSize);
  17.     }
  18.    //主要就是这个方法解析了request并封装成了File类型
  19.      很明显使用了commons-fileupload.jar的框架
  20.   public void parse(HttpServletRequest servletRequest, String saveDir)
  21.             throws IOException {
  22.         DiskFileItemFactory fac = new DiskFileItemFactory();
  23.         // Make sure that the data is written to file
  24.         //控制上传文件大小的阀值设置成了0,这就会直接写到临时文件去了
  25.         fac.setSizeThreshold(0);
  26.         if (saveDir != null) {
  27.             //设置临时目录
  28.             fac.setRepository(new File(saveDir));
  29.         }
  30.         // Parse the request
  31.         try {
  32.             ServletFileUpload upload = new ServletFileUpload(fac);
  33.             upload.setSizeMax(maxSize);
  34.             List items = upload.parseRequest(createRequestContext(servletRequest));
  35.             for (Object item1 : items) {
  36.                 FileItem item = (FileItem) item1;
  37.                 if (LOG.isDebugEnabled()) LOG.debug("Found item " + item.getFieldName());
  38.                 if (item.isFormField()) {
  39.                     LOG.debug("Item is a normal form field");
  40.                     List<String> values;
  41.                     if (params.get(item.getFieldName()) != null) {
  42.                         values = params.get(item.getFieldName());
  43.                     } else {
  44.                         values = new ArrayList<String>();
  45.                     }
  46.                     // note: see http://jira.opensymphony.com/browse/WW-633
  47.                     // basically, in some cases the charset may be null, so
  48.                     // we're just going to try to "other" method (no idea if this
  49.                     // will work)
  50.                     String charset = servletRequest.getCharacterEncoding();
  51.                     if (charset != null) {
  52.                         values.add(item.getString(charset));
  53.                     } else {
  54.                         values.add(item.getString());
  55.                     }
  56.                     params.put(item.getFieldName(), values);
  57.                 } else {
  58.                     LOG.debug("Item is a file upload");
  59.                     // Skip file uploads that don't have a file name - meaning that no file was selected.
  60.                     if (item.getName() == null || item.getName().trim().length() < 1) {
  61.                         LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
  62.                         continue;
  63.                     }
  64.                      
  65.                       List<FileItem> values;
  66.                     if (files.get(item.getFieldName()) != null) {
  67.                         values = files.get(item.getFieldName());
  68.                     } else {
  69.                         values = new ArrayList<FileItem>();
  70.                     }
  71.                     values.add(item);
  72.                     //把解析出来的文件都放到这里
  73.                     files.put(item.getFieldName(), values);
  74.                 }
  75.             }
  76.         } catch (FileUploadException e) {
  77.             LOG.error("Unable to parse request", e);
  78.             errors.add(e.getMessage());
  79.         }
  80.     }
  81.     
  82. //根据文件名返回File数组
  83.  public File[] getFile(String fieldName) {
  84.         List items = (List) files.get(fieldName);
  85.         if (items == null) {
  86.             return null;
  87.         }
  88.         List<File> fileList = new ArrayList<File>(items.size());
  89.         for (int i = 0; i < items.size(); i++) {
  90.             DiskFileItem fileItem = (DiskFileItem) items.get(i);
  91.             fileList.add(fileItem.getStoreLocation());
  92.         }
  93.         return (File[]) fileList.toArray(new File[fileList.size()]);
  94.     }
  95. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值