struts2 实现文件上传原理

来源:互联网 发布:网络教育有毕业证吗 编辑:程序博客网 时间:2024/06/05 08:44

struts2 实现文件上传原理

  通过struts2实现文件上传功能,主要jar包是不可少的包括:

复制代码
aopalliance.jar  ------------------------------------为aop(面向切面)提供了最普通和通用的接口asm-3.3.jar  ----------------------------------------操作java字节码的类库asm-commons-3.3.jar  --------------------------------提供了基于事件的表现形式commons-fileupload-1.2.2.jar  -----------------------实现struts文件的上传下载commons-io-2.0.1.jar  -------------------------------文件上传读取文件commons-lang3-3.1.jar  ------------------------------为java.lang包提供扩展commons-logging-1.1.1.jar  --------------------------jakarta的通用日志记录包freemarker-2.3.19.jar  ------------------------------FreeMarker是一个模板引擎,一个基于模板生成文本输 出的通用工具javassist-3.11.0.GA.jar  ----------------------------Javassist是一个开源的分析、编辑和创建Java字节码的类库ognl-3.0.5.jar  -------------------------------------标签库struts2-convention-plugin-2.3.3.jar  ----------------在默认情况下该公约插件查找操作类在以下软件包支,struts2的行为或行动,任何包相匹配这些名称将被考虑struts2-core-2.3.3.jar  -----------------------------strut2的核心处理包struts2-json-plugin-2.3.3.jar  ----------------------struts2所用到的json插件包xwork-core-2.3.3.jar  -------------------------------webwork的核心库
复制代码

  1.  struts2没有提供自己的请求解析器,也就是就struts2不会自己去处理multipart/form-data的请求,它需要调用其他请求解析器,将HTTP请求中的表单域解析出来。但struts2在原有的上传解析器基础上做了进一步封装,更进一步简化了文件上传。 

  2. struts2默认使用的是Jakarta的Common-FileUpload框架来上传文件,因此,要在web应用中增加Jar文 件:commons-fileupload-1.2.jar和commons-io-1.3.1.jar。它在原上传框架上做了进一步封装,简化了文件上传的代码实现,取消了不同上传框架上的编程差异。 

  3. 如果要改成其它的文件上传框架,可以修改struts.multipart.parser或(struts.multipart.hander)常量的值为cos/pell,默认值是jakata。并在classpath中增加相应上传组件的类库。

  4. struts2所用的文件上传框架都是先将Http上传的文件保存到临时目录下, 然后struts2通过FileUpload拦截器将文件绑定到Action实例中。临时目录可以在struts.xml中配置,如果不配置则会将临时文件存在默认临时目录下(具体目录忘记了。。)。也可以理解为struts2上传文件是通过Action完成的,而Action的工作主要是将缓存目录中的文件复制到目的地址,在Action执行之前,系统已经将文件上传到服务器的临时目录中了。

  5. struts2的文件上传工作都要通过FileUploadInterceptor,这个拦截器对文件大小,文件类型,文件信息进行了拦截设置,但是并没有做IO的监控操作。 

复制代码
贴出FileUploadInterceptor中的一段代码:可以看出当http发出上传请求时,是由MultiPartRequestWrapper类来提供文件名称及文件元素的处理操作的。 1 public String intercept(ActionInvocation invocation) throws Exception { 2         ActionContext ac = invocation.getInvocationContext(); 3  4         HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST); 5  6         if (!(request instanceof MultiPartRequestWrapper)) { 7             if (LOG.isDebugEnabled()) { 8                 ActionProxy proxy = invocation.getProxy(); 9                 LOG.debug(getTextMessage("struts.messages.bypass.request", new String[]{proxy.getNamespace(), proxy.getActionName()}));10             }11 12             return invocation.invoke();13         }14 15         ValidationAware validation = null;16 17         Object action = invocation.getAction();18 19         if (action instanceof ValidationAware) {20             validation = (ValidationAware) action;21         }22 23         MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;24 25         if (multiWrapper.hasErrors()) {26             for (String error : multiWrapper.getErrors()) {27                 if (validation != null) {28                     validation.addActionError(error);29                 }30             }31         }32 33         // bind allowed Files34         Enumeration fileParameterNames = multiWrapper.getFileParameterNames();35         while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {36             // get the value of this input tag37             String inputName = (String) fileParameterNames.nextElement();38 39             // get the content type40             String[] contentType = multiWrapper.getContentTypes(inputName);41 42             if (isNonEmpty(contentType)) {43                 // get the name of the file from the input tag44                 String[] fileName = multiWrapper.getFileNames(inputName);45 46                 if (isNonEmpty(fileName)) {47                     // get a File object for the uploaded File48                     File[] files = multiWrapper.getFiles(inputName);49                     if (files != null && files.length > 0) {50                         List<File> acceptedFiles = new ArrayList<File>(files.length);51                         List<String> acceptedContentTypes = new ArrayList<String>(files.length);52                         List<String> acceptedFileNames = new ArrayList<String>(files.length);53                         String contentTypeName = inputName + "ContentType";54                         String fileNameName = inputName + "FileName";55 56                         for (int index = 0; index < files.length; index++) {57                             if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation)) {58                                 acceptedFiles.add(files[index]);59                                 acceptedContentTypes.add(contentType[index]);60                                 acceptedFileNames.add(fileName[index]);61                             }62                         }63 64                         if (!acceptedFiles.isEmpty()) {65                             Map<String, Object> params = ac.getParameters();66 67                             params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));68                             params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));69                             params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));70                         }71                     }72                 } else {73                     if (LOG.isWarnEnabled()) {74                         LOG.warn(getTextMessage(action, "struts.messages.invalid.file", new String[]{inputName}));75                     }76                 }77             } else {78                 if (LOG.isWarnEnabled()) {79                     LOG.warn(getTextMessage(action, "struts.messages.invalid.content.type", new String[]{inputName}));80                 }81             }82         }83 84         // invoke action85         return invocation.invoke();86     }
复制代码

   6. 继续深入,MartiPartRequestWarpper对MartiPartRequest接口的主要功能进行的封装应用,因此要继续深入到MartiPartRequest接口的实现类,可以了解到struts2是如何对文件上传进行控制操作的。

复制代码
 1 MartiPartRequestWrapper的构造方法: 2  3 public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir, LocaleProvider provider) { 4         super(request); 5         errors = new ArrayList<String>(); 6         multi = multiPartRequest; 7         defaultLocale = provider.getLocale(); 8         setLocale(request); 9         try {10             multi.parse(request, saveDir);11             for (String error : multi.getErrors()) {12                 addError(error);13             }14         } catch (IOException e) {15             if (LOG.isWarnEnabled()) {16                 LOG.warn(e.getMessage(), e);17             }18             addError(buildErrorMessage(e, new Object[] {e.getMessage()}));19         } 20     }
复制代码

  7. 从上面的代码中可以知道,MultiPartRequest提供了主要的功能框架,JarkatMultiPartRequest是MultiPartRequest的实现类,对文件上传具体功能进行了封装。可以通过改写此类实现对文件上传进度的监控,实现进度条功能(在后面的知识中详细介绍进度条功能的实现)。

  在JarkatMultiPartRequest源码中提供了方法parse(HttpServletRequest request, String saveDir),通过调用progressUpload(HttpServletRequest request, String saveDir)对文件上传进度进行控制。在其中通过DiskFileItemFactory、 ServletFileUpload对上传文件进行加载,并读取。

0 0
原创粉丝点击