隨筆 - 63  文章 - 0  trackbacks - 0
          <2009年4月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          問題:

                  struts2 使用jakarta 上傳文件時(shí),如果上傳文件的大小超出commons fileupload(jakarta上傳文件還是依賴commons-fileupload)設(shè)置的大小就會(huì)在進(jìn)入action以前拋出異常.
                  如果想返回用戶的輸入界面(input),那么頁面原來的參數(shù)會(huì)丟失。

          首先看一下struts2 執(zhí)行一個(gè)action的過程

          1.  將用戶請(qǐng)求發(fā)給org.apache.struts2.dispatcher.Dispatcher,
               wrapRequest(HttpServletRequest request, ServletContext servletContext)  方法會(huì)判斷是否"multipart/form-data",如果是建立一個(gè)multiPartRequest 的實(shí)例,并且建立MultiPartRequestWrapper

          寫道
          ...if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
                 MultiPartRequest multi = getContainer().getInstance(MultiPartRequest.class);
                 request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));
          } else {
                 request = new StrutsRequestWrapper(request);
          }

           

          2. 建立 MultiPartRequestWrapper 時(shí)解析(parse) request,

          Java代碼
          1. public void parse(HttpServletRequest servletRequest, String saveDir)   
          2.             throws IOException {   
          3.         DiskFileItemFactory fac = new DiskFileItemFactory();   
          4.         // Make sure that the data is written to file   
          5.         fac.setSizeThreshold(0);   
          6.         if (saveDir != null) {   
          7.             fac.setRepository(new File(saveDir));   
          8.         }   
          9.   
          10.         // Parse the request   
          11.         try {   
          12.             ServletFileUpload upload = new ServletFileUpload(fac);   
          13.             upload.setSizeMax(maxSize);   
          14.             //upload 解析request并取得頁面參數(shù)   
          15.         List items = upload.parseRequest(createRequestContext(servletRequest));   
          16.         ......   
          17.           

           3.我們看一下ServletFileUpload(commons-fileupload v1.1.1) 的parseRequest做了什么

          Java代碼
          1. public List /* FileItem */ parseRequest(RequestContext ctx)   
          2.            throws FileUploadException {   
          3.        if (ctx == null) {   
          4.            throw new NullPointerException("ctx parameter");   
          5.        }   
          6.   
          7.        ArrayList items = new ArrayList();   
          8.        String contentType = ctx.getContentType();   
          9.   
          10.        if ((null == contentType)   
          11.            || (!contentType.toLowerCase().startsWith(MULTIPART))) {   
          12.            throw new InvalidContentTypeException(   
          13.                "the request doesn't contain a "  
          14.                + MULTIPART_FORM_DATA   
          15.                + " or "  
          16.                + MULTIPART_MIXED   
          17.                + " stream, content type header is "  
          18.                + contentType);   
          19.        }   
          20.        int requestSize = ctx.getContentLength();   
          21.           
          22.        if (requestSize == -1) {   
          23.            throw new UnknownSizeException(   
          24.                "the request was rejected because its size is unknown");   
          25.        }   
          26.        //關(guān)鍵就這里了,大小超出的異常,這里是所有上傳文件合計(jì)的大小,如果超出就拋出異常   
          27.        //這時(shí)上層是拿不到保存參數(shù)的items的   
          28.        if (sizeMax >= 0 && requestSize > sizeMax) {   
          29.            throw new SizeLimitExceededException(   
          30.                "the request was rejected because its size (" + requestSize   
          31.                + ") exceeds the configured maximum (" + sizeMax + ")",   
          32.                requestSize, sizeMax);   
          33.        }   
          34.   
          35.        String charEncoding = headerEncoding;   
          36.        if (charEncoding == null) {   
          37.            charEncoding = ctx.getCharacterEncoding();   
          38.        }   
          39.   
          40.        try {   
          41.            byte[] boundary = getBoundary(contentType);   
          42.            if (boundary == null) {   
          43.                throw new FileUploadException(   
          44.                        "the request was rejected because "  
          45.                        + "no multipart boundary was found");   
          46.            }   
          47.   
          48.            InputStream input = ctx.getInputStream();   
          49.   
          50.            MultipartStream multi = new MultipartStream(input, boundary);   
          51.            multi.setHeaderEncoding(charEncoding);   
          52.   
          53.            boolean nextPart = multi.skipPreamble();   
          54.            while (nextPart) {   
          55.                Map headers = parseHeaders(multi.readHeaders());   
          56.                String fieldName = getFieldName(headers);   
          57.                if (fieldName != null) {   
          58.                    String subContentType = getHeader(headers, CONTENT_TYPE);   
          59.                    if (subContentType != null && subContentType   
          60.                        .toLowerCase().startsWith(MULTIPART_MIXED)) {   
          61.                        // Multiple files.   
          62.                        byte[] subBoundary = getBoundary(subContentType);   
          63.                        multi.setBoundary(subBoundary);   
          64.                        boolean nextSubPart = multi.skipPreamble();   
          65.                        while (nextSubPart) {   
          66.                            headers = parseHeaders(multi.readHeaders());   
          67.                            if (getFileName(headers) != null) {   
          68.                                FileItem item =   
          69.                                        createItem(headers, false);   
          70.                                OutputStream os = item.getOutputStream();   
          71.                                try {   
          72.                                    multi.readBodyData(os);   
          73.                                } finally {   
          74.                                    os.close();   
          75.                                }   
          76.                                items.add(item);   
          77.                            } else {   
          78.                                // Ignore anything but files inside   
          79.                                // multipart/mixed.   
          80.                                multi.discardBodyData();   
          81.                            }   
          82.                            nextSubPart = multi.readBoundary();   
          83.                        }   
          84.                        multi.setBoundary(boundary);   
          85.                    } else {   
          86.                        FileItem item = createItem(headers,   
          87.                                getFileName(headers) == null);   
          88.                        OutputStream os = item.getOutputStream();   
          89.                        try {   
          90.                            multi.readBodyData(os);   
          91.                        } finally {   
          92.                            os.close();   
          93.                        }   
          94.                        items.add(item);   
          95.                    }   
          96.                } else {   
          97.                    // Skip this part.   
          98.                    multi.discardBodyData();   
          99.                }   
          100.                nextPart = multi.readBoundary();   
          101.            }   
          102.        } catch (IOException e) {   
          103.            throw new FileUploadException(   
          104.                "Processing of " + MULTIPART_FORM_DATA   
          105.                    + " request failed. " + e.getMessage());   
          106.        }   
          107.   
          108.        return items;   
          109.    }  

           4.這之后才開始逐個(gè)進(jìn)入interceptor,見DefaultActionInvocation.invoke()

          Java代碼
          1. ....   
          2. //遞歸interceptor   
          3. if (interceptors.hasNext()) {   
          4.                 final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();   
          5.                 UtilTimerStack.profile("interceptor: "+interceptor.getName(),    
          6.                         new UtilTimerStack.ProfilingBlock<String>() {   
          7.                             public String doProfiling() throws Exception {   
          8.                                 resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);   
          9.                                 return null;   
          10.                             }   
          11.                 });   
          12.             } else {   
          13.                         //如果有errors,resultCode會(huì)得到‘input’   
          14.                 resultCode = invokeActionOnly();   
          15.             }   
          16. ...  

           5.我們的目標(biāo)就是返回input并且保留頁面原來的參數(shù),那么就要不要讓ServletFileUpload拋出異常,并且要讓strusts使用我們自己的jakart.

           6.寫自己的ServletFileUpload

          Java代碼
          1. /*  
          2.  * Copyright 2001-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 com.infowarelab.newcentury.web.util;   
          17.   
          18. import java.io.IOException;   
          19. import java.io.InputStream;   
          20. import java.io.OutputStream;   
          21. import java.util.ArrayList;   
          22. import java.util.List;   
          23. import java.util.Map;   
          24.   
          25. import javax.servlet.http.HttpServletRequest;   
          26.   
          27. import org.apache.commons.fileupload.FileItem;   
          28. import org.apache.commons.fileupload.FileItemFactory;   
          29. import org.apache.commons.fileupload.FileUpload;   
          30. import org.apache.commons.fileupload.FileUploadException;   
          31. import org.apache.commons.fileupload.MultipartStream;   
          32. import org.apache.commons.fileupload.RequestContext;   
          33. import org.apache.commons.fileupload.servlet.ServletRequestContext;   
          34. import org.apache.log4j.Logger;   
          35.   
          36. /**  
          37.   * come from commons-fileupload  
          38.   * @author alfred  
          39.  */  
          40. public class ServletFileUpload extends FileUpload {   
          41.   
          42.     // ---------------------------------------------------------- Class methods   
          43.   
          44.     /**  
          45.      * Logger for this class  
          46.      */  
          47.     private static final Logger logger = Logger.getLogger(ServletFileUpload.class);   
          48.     private List<String> errors = new ArrayList<String>();   
          49.   
          50.     /**  
          51.      * Constructs an uninitialised instance of this class. A factory must be  
          52.      * configured, using <code>setFileItemFactory()</code>, before attempting  
          53.      * to parse requests.  
          54.      *   
          55.      * @see FileUpload#FileUpload(FileItemFactory)  
          56.      */  
          57.     public ServletFileUpload() {   
          58.         super();   
          59.     }   
          60.   
          61.     /**  
          62.      * Constructs an instance of this class which uses the supplied factory to  
          63.      * create <code>FileItem</code> instances.  
          64.      *   
          65.      * @see FileUpload#FileUpload()  
          66.      */  
          67.     public ServletFileUpload(FileItemFactory fileItemFactory) {   
          68.         super(fileItemFactory);   
          69.     }   
          70.     /**  
          71.      * overide parseRequest  
          72.      */  
          73.     public List /* FileItem */parseRequest(RequestContext ctx) throws FileUploadException {   
          74.         if (ctx == null) {   
          75.             throw new NullPointerException("ctx parameter");   
          76.         }   
          77.   
          78.         ArrayList items = new ArrayList();   
          79.         String contentType = ctx.getContentType();   
          80.   
          81.         if ((null == contentType) || (!contentType.toLowerCase().startsWith(MULTIPART))) {   
          82.             throw new InvalidContentTypeException("the request doesn't contain a " + MULTIPART_FORM_DATA + " or "  
          83.                     + MULTIPART_MIXED + " stream, content type header is " + contentType);   
          84.         }   
          85.         int requestSize = ctx.getContentLength();   
          86.   
          87.         if (requestSize == -1) {   
          88.             // throw new UnknownSizeException(   
          89.             // "the request was rejected because its size is unknown");   
          90.             logger.error("the request was rejected because its size is unknown");   
          91.             errors.add("the request was rejected because its size is unknown");   
          92.         }   
          93.   
          94.         String charEncoding = getHeaderEncoding();   
          95.         if (charEncoding == null) {   
          96.             charEncoding = ctx.getCharacterEncoding();   
          97.         }   
          98.   
          99.         try {   
          100.             byte[] boundary = getBoundary(contentType);   
          101.             if (boundary == null) {   
          102.                 // throw new FileUploadException(   
          103.                 // "the request was rejected because "   
          104.                 // + "no multipart boundary was found");   
          105.                 logger.error("the request was rejected because no multipart boundary was found");   
          106.                 errors.add("the request was rejected because no multipart boundary was found");   
          107.             }   
          108.   
          109.             InputStream input = ctx.getInputStream();   
          110.   
          111.             MultipartStream multi = new MultipartStream(input, boundary);   
          112.             multi.setHeaderEncoding(charEncoding);   
          113.   
          114.             boolean nextPart = multi.skipPreamble();   
          115.             while (nextPart) {   
          116.                 Map headers = parseHeaders(multi.readHeaders());   
          117.                 String fieldName = getFieldName(headers);   
          118.                 if (fieldName != null) {   
          119.                     String subContentType = getHeader(headers, CONTENT_TYPE);   
          120.                     if (subContentType != null && subContentType.toLowerCase().startsWith(MULTIPART_MIXED)) {   
          121.                         // Multiple files.   
          122.                         byte[] subBoundary = getBoundary(subContentType);   
          123.                         multi.setBoundary(subBoundary);   
          124.                         boolean nextSubPart = multi.skipPreamble();   
          125.                         while (nextSubPart) {   
          126.                             headers = parseHeaders(multi.readHeaders());   
          127.                             if (getFileName(headers) != null) {   
          128.                                 FileItem item = createItem(headers, false);   
          129.                                 OutputStream os = item.getOutputStream();   
          130.                                 try {   
          131.                                     multi.readBodyData(os);   
          132.                                 } finally {   
          133.                                     os.close();   
          134.                                 }   
          135.                                 items.add(item);   
          136.                             } else {   
          137.                                 // Ignore anything but files inside   
          138.                                 // multipart/mixed.   
          139.                                 multi.discardBodyData();   
          140.                             }   
          141.                             nextSubPart = multi.readBoundary();   
          142.                         }   
          143.                         multi.setBoundary(boundary);   
          144.                     } else {   
          145.                         FileItem item = createItem(headers, getFileName(headers) == null);   
          146.                         OutputStream os = item.getOutputStream();   
          147.                         try {   
          148.                             multi.readBodyData(os);   
          149.                         } finally {   
          150.                             os.close();   
          151.                         }   
          152.                         items.add(item);   
          153.                     }   
          154.                 } else {   
          155.                     // Skip this part.   
          156.                     multi.discardBodyData();   
          157.                 }   
          158.                 nextPart = multi.readBoundary();   
          159.             }   
          160.             // remove SizeLimitExceededException   
          161.             if (getSizeMax() >= 0 && requestSize > getSizeMax()) {   
          162.                 // throw new SizeLimitExceededException(   
          163.                 // "the request was rejected because its size (" + requestSize   
          164.                 // + ") exceeds the configured maximum (" + getSizeMax() + ")",   
          165.                 // requestSize, getSizeMax());   
          166.                 logger.error("the request was rejected because its size (" + requestSize   
          167.                         + ") exceeds the configured maximum (" + getSizeMax() + ")");   
          168.             }   
          169.         } catch (IOException e) {   
          170.             logger.error("Processing of " + MULTIPART_FORM_DATA + " request failed. " + e.getMessage());   
          171.             errors.add("Processing of " + MULTIPART_FORM_DATA + " request failed. " + e.getMessage());   
          172.             // throw new FileUploadException(   
          173.             // "Processing of " + MULTIPART_FORM_DATA   
          174.             // + " request failed. " + e.getMessage());   
          175.         }    
          176.            
          177.         return items;   
          178.     }   
          179.   
          180.     /**  
          181.      * @return the errors  
          182.      */  
          183.     public List<String> getErrors() {   
          184.         return errors;   
          185.     }   
          186.   
          187.     /**  
          188.      * @param errors the errors to set  
          189.      */  
          190.     public void setErrors(List<String> errors) {   
          191.         this.errors = errors;   
          192.     }   
          193.   
          194. }  

           

          7.copy org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest,只是import上面自己的ServletFileUpload.這樣就可以保存頁面的所有參數(shù)了。

          8.更改struts配置文件加入你自己的JakartaMultiReques

          Xml代碼
          1. <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"    
          2. ame="jakarta_yourself"    
          3.        class="com.xxxxx.util.JakartaMultiPartRequest"    
          4. cope="default" optional="true" />  

           9.更改struts.properties

          struts.multipart.parser=jakarta_yourself

          10.就OK啦

           

           

          posted on 2009-04-14 12:50 lanxin1020 閱讀(2229) 評(píng)論(0)  編輯  收藏 所屬分類: struts2
          主站蜘蛛池模板: 壤塘县| 象州县| 徐水县| 康乐县| 宁安市| 淄博市| 钟山县| 江口县| 酒泉市| 龙州县| 湖南省| 奉贤区| 喀喇沁旗| 如东县| 琼结县| 五华县| 绥芬河市| 巴林左旗| 那曲县| 广饶县| 乃东县| 金华市| 水富县| 榆树市| 合川市| 井陉县| 义乌市| 沂源县| 定南县| 和平县| 蓬安县| 甘孜县| 纳雍县| 凤山县| 石门县| 丰城市| 裕民县| 安塞县| 锦屏县| 兴化市| 苗栗县|