struts2中文件上传详解

struts2中文件上传的二个限制,一个是struts.multipart.maxSize,如果不设置,struts2 的核心包下的default.properties文件里有默认的大小设置struts.multipart.maxSize=2097152,即2M. 这是struts2文件上传的第一道关.

第二道关是inteceptor中的maximumSize. 当真实的文件大小能通过第一道关时.针对不同的action中配置的inteceptor,maximumSize才能发挥相应的拦截作用.

比如struts.multipart.maxSize=50M. actionA中inteceptorA的maximumSize=30M. actionB中inteceptorB的maximumSize=10M.

struts.multipart.maxSize=50M对于inteceptorA,B都会起到第一关的作用.而inteceptorA和inteceptorB可以在通过第一关之后,根据自己的业务定制各自针对拦截器起作用的maximumSize

如果真实的文件>50M. 抛出会抛出the request was rejected because its size (XXXX) exceeds the configured maximum (XXXX)异常,他是不能被国际化的,因为这个信息是commons-fileupload组件抛出的,是不支持国际化这信息.

struts2.2 org.apache.commons.fileupload.FileUploadBase.java中

 /**
  * Creates a new instance.
  * @param ctx The request context.
  * @throws FileUploadException An error occurred while
  *   parsing the request.
  * @throws IOException An I/O error occurred.
  */ 
 FileItemIteratorImpl(RequestContext ctx) 
         throws FileUploadException, IOException { 
     if (ctx == null) { 
         throw new NullPointerException("ctx parameter"); 
     } 
  
     String contentType = ctx.getContentType(); 
     if ((null == contentType) 
             || (!contentType.toLowerCase().startsWith(MULTIPART))) { 
         throw new InvalidContentTypeException( 
                 "the request doesn't contain a " 
                 + MULTIPART_FORM_DATA 
                 + " or " 
                 + MULTIPART_MIXED 
                 + " stream, content type header is " 
                 + contentType); 
     } 
  
     InputStream input = ctx.getInputStream(); 
  
     if (sizeMax >= 0) { 
         int requestSize = ctx.getContentLength(); 
         if (requestSize == -1) { 
             input = new LimitedInputStream(input, sizeMax) { 
                 protected void raiseError(long pSizeMax, long pCount) 
                         throws IOException { 
                     FileUploadException ex = 
                         new SizeLimitExceededException( 
                             "the request was rejected because" 
                             + " its size (" + pCount 
                             + ") exceeds the configured maximum" 
                             + " (" + pSizeMax + ")", 
                             pCount, pSizeMax); 
                     throw new FileUploadIOException(ex); 
                 } 
             }; 
         } else { 
 ///问题就在这里//////////////////////////////////// 
             if (sizeMax >= 0 && requestSize > sizeMax) { 
                 throw new SizeLimitExceededException( 
                         "the request was rejected because its size (" 
                         + requestSize 
                         + ") exceeds the configured maximum (" 
                         + sizeMax + ")", 
                         requestSize, sizeMax); 
             } 
         } 
     } 
  
     String charEncoding = headerEncoding; 
     if (charEncoding == null) { 
         charEncoding = ctx.getCharacterEncoding(); 
     } 
  
     boundary = getBoundary(contentType); 
     if (boundary == null) { 
         throw new FileUploadException( 
                 "the request was rejected because " 
                 + "no multipart boundary was found"); 
     } 
  
     notifier = new MultipartStream.ProgressNotifier(listener, 
             ctx.getContentLength()); 
     multi = new MultipartStream(input, boundary, notifier); 
     multi.setHeaderEncoding(charEncoding); 
  
     skipPreamble = true; 
     findNextItem(); 

 

 

如果InteceptorA上传的是40M的真实文件.那么此时拦截器InteceptorA会访问国际化信息:struts.messages.error.file.too.larges对应的值.

当且仅当上传文件<=30M的时候,InteceptorA才会成功上传.

下面是解决struts.multipart.maxSize提示信息不友好的问题.

当超过50M时.commons-fileupload抛出运行时异常,struts2会把这个异常看到是action级别的异常.所以会将异常信息

the request was rejected because its size (XXXX) exceeds the configured maximum (XXXX)写到actionError里面.我们需要做的就是在action里覆盖addActionError方法

   

@Override
    public void addActionError(String anErrorMessage) {
        //改从国际化里取值
        if (anErrorMessage
                .startsWith("the request was rejected because its size")) {
            super.addActionError(getText("struts.multipart.maxSize.limit"));
        } else {
            super.addActionError(anErrorMessage);
        }
    }

 

相应的配置文件

struts.multipart.maxSize.limit=系统上传的文件最大为50M
struts.messages.error.file.too.larges=新广告批量上传的文件最大为5M
struts.messages.error.content.type.not.allowed=上传的文件格式目前仅支持xls格式
struts.messages.error.uploading=上传文件失败
struts.messages.invalid.token=您已经提交了表单,请不要重复提交。
fileupload.filenums.exceed=已经有超过5个文件在运行,请稍候再试
filedownload.rows.exceed=由于您选择的广告组内广告数量太多,请分组下载
accountNotExist=客户不存在
invalidTask=无效的任务

注意,由于inteceptor中途返回,原来页面上输入的其他文本内容也都不见了,也就是说params注入失败。

这个是没办法的,因为这个异常是在文件上传之前捕获的,文件未上传,同时params也为注入,所以这时最好重定向到一个jsp教程文件,提示上传失败,然后重写填写相应信息。

解决办法:最好跳到一个专门显示错误的页.而不要返回操作页.

-------------------------------------------------------------------------------------------

注意,拦截器所谓的同名配置覆盖,是重复执行的,比如defaultStack中是包含fileUpload,token的. 如果将<interceptor-ref name="defaultStack" />放到显示定义的拦截器之后,会覆盖显示定义的拦截器.

下面是正确的拦截器顺序:

 

        <action name="BatchMIADOperation!*" method="{1}"
            class="com.*****.***.action.multiidea.batchad.BatchMIADOperationAction">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="fileUpload">
                <param name="maximumSize">5242880</param>
                <!--
                    <param name="allowedTypes">
                    application/vnd.ms-excel
                    </param>
                -->
            </interceptor-ref>
            <interceptor-ref name="token">
                <param name="excludeMethods">
                    init,search,updateBatchCpcMatch,batchExportMIAD,downloadWhenError
                </param>
            </interceptor-ref>
            <result name="input">
                /WEB-INF/jsp/multiidea/batchad/BatchMIAD.jsp
            </result>
            <result name="success">
                /WEB-INF/jsp/multiidea/batchad/BatchMIAD.jsp
            </result>
            <result name="invalid.token">
                /WEB-INF/jsp/multiidea/batchad/BatchMIAD.jsp
            </result>
        </action>

时间: 2024-09-18 00:48:38

struts2中文件上传详解的相关文章

struts2中文件上传拦截器 是不是不能在多个action中引用???

问题描述 <global-results> <result name="input">/message.jsp</result></global-results><!--定义全局的返回视图--><action name="updateHead" class="updateHead"> <interceptor-ref name="fileUpload"

Struts2中文件上传请求转发问题求解

问题描述 嗨,各位,我想实现一个Struts2的文件上传功能,客户端通过jsp页面上传文件,Struts2服务器端根据一定的策略将这个上传请求转发到别的机器上的Struts2子服务器端,并在子服务器端接收该服务.目前我使用的方式是Struts2+socket传输.试过用Servlet的转发和重定向都不行,不知道有没有人做过相关的工作 问题补充:283433775 写道 解决方案 一般来说,不同域的request是不可以重用的,所以按理说是不行的,但我觉得既然是request请求,他们的差别就在于

Swift HTTP网络操作库Alamofire实现文件上传详解

六,使用Alamofire进行文件上传 1,Alamofire支持如下上传类型: File Data Stream MultipartFormData 2,使用文件流的形式上传文件 let fileURL = NSBundle.mainBundle().URLForResource("hangge", withExtension: "zip")   Alamofire.upload(.POST, "http://www.hangge.com/upload.

java ftp文件上传详解

先我们来看两段简单的代码 将本地文件上传到ftp服务器上,代码如下:  @test  public void testuploadfromdisk(){   try {    fileinputstream in=new fileinputstream(new file("d:/test.txt"));    boolean flag = uploadfile("127.0.0.1", 21, "test", "test",

PHP文件上传详解

HTML部分:    代码如下 复制代码 <form action="upload.php" method="post" enctype="multipart/form-data"> 上传:<input type="file" name="myfile" /> <input type="submit" name="submit" valu

php 入门级文件上传详解

上传文件我们少不了move_uploaded_file函数本函数检查并确保由 file 指定的文件是合法的上传文件(即通过 php教程 的 http post 上传机制所上传的).如果文件合法,则将其移动为由 newloc 指定的文件. 如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false. 如果 file 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false,此外还

Multipart/form-data POST文件上传详解

理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下:      <form method="post"action="http://www.111cn.net" >          <inputtype="text" name="txt1">          <inputtype="text" name=&

struts2的文件上传和文件下载

实现使用Struts2文件上传和文件下载: 注意点: (1)对应表单的file1和私有成员变量的名称必须一致  <input type="file" name="file1"/>        private File file1;   (2)限制上传文件大小和类型的格式是定死的,最好记住,记不住知道去哪里查:虽然不做要求,完全懂框架内部的机制,但是找一些东西还是需要能找到的,这样你可以很好的实现一些功能,因为这些关键字都是框架底层定义好的,图一是找到配

JavaWeb中struts2实现文件上传下载功能实例解析_java

在做B/S系统时,通常会涉及到上传文件和下载文件,在没接struts2框架之前,我们都是使用apache下面的commons子项目的FileUpload组件来进行文件的上传,但是那样做的话,代码看起来比较繁琐,而且不灵活,在学习了struts2后,struts2为文件上传下载提供了更好的实现机制,在这里我分别就单文件上传和多文件上传的源代码进行一下讲解,这里需要导入文件下载上传的两个jar文件,一个是commons-fileupload-1.2.2.jar,另一个是commons-io-2.0.