• 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 Files 34 Enumeration fileParameterNames = multiWrapper.getFileParameterNames(); 35 while (fileParameterNames != null && fileParameterNames.hasMoreElements()) { 36 // get the value of this input tag 37 String inputName = (String) fileParameterNames.nextElement(); 38 39 // get the content type 40 String[] contentType = multiWrapper.getContentTypes(inputName); 41 42 if (isNonEmpty(contentType)) { 43 // get the name of the file from the input tag 44 String[] fileName = multiWrapper.getFileNames(inputName); 45 46 if (isNonEmpty(fileName)) { 47 // get a File object for the uploaded File 48 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 action 85 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对上传文件进行加载,并读取。

  • 相关阅读:
    Linux一些工具命令
    IDC运维_2
    计算机网络基础_1
    Shell编程基础2
    Shell编程进阶3
    注销无效的vcenter/vcsa
    Dapper中,针对MySQL的Like参数化查询
    墨天轮访谈 | 拓扑岭雷鹏:数据库新思维下的弹性压缩与内存计算
    九问 GBase | 如何看待“科技制裁”?如何助力中国数据库国产化落地?
    墨天轮访谈 | 百度云邱学达:GaiaDB如何解决云上场景的业务需求?
  • 原文地址:https://www.cnblogs.com/daisyleamo/p/3066041.html
Copyright © 2020-2023  润新知