一:首先看一下程序執行中出現的對應報錯信息,如下所示:
[WARN ] 2015-03-03 15:31:11 :Unable to parse request org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (78871114) exceeds the configured maximum (52428800) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:937) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parseRequest(JakartaMultiPartRequest.java:151) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.processUpload(JakartaMultiPartRequest.java:90) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parse(JakartaMultiPartRequest.java:80) at org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper.<init>(MultiPartRequestWrapper.java:75) at org.apache.struts2.dispatcher.Dispatcher.wrapRequest(Dispatcher.java:740) at org.apache.struts2.dispatcher.ng.PrepareOperations.wrapRequest(PrepareOperations.java:131) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:83) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.frame.action.ChineseFilter.doFilter(ChineseFilter.java:66) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619) [WARN ] 2015-03-03 15:31:11 :Could not find token name in params.
類似的問題相信很多人都遇到過,也曉得如何解決,我這里記錄下來也是為了讓自己對這個問題理解的更好一點,當然,我下面記錄的情況都是在我的機器上實際都試驗了的,下面是我根據自己的實驗以及網上的相關資料的小結。
二:限制Struts2文件上傳的三種情況
1:Struts2對應的配置文件中的配置的限制
struts.multipart.maxSize=上傳文件的最大值(單位是字節)這個配置是控制整個項目一次性上傳的文件的最大值!如果實際上傳的文件超過了此配置的大小那么就會報 org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (78871114) exceeds the configured maximum (52428800),這個異常信息!
這個配置有對應的默認值,如果不設置則使用默認的設置(針對我自己的項目這個默認配置的所在位置是:struts2-core-2.3.1.2.jar包中的org\apache\struts2\default.properties文件中)struts.multipart.maxSize=2097152,代表默認上傳的文件最大值是2M,如果我們想修改它也是很容易的,有以下兩種方式:
1)在struts.properties文件中配置,比如:struts.multipart.maxSize=52428800 (代表上傳的文件的最大值是50M)
2)在struts.xml文件中配置,比如:<constant name="struts.multipart.maxSize" value="52428800"/>(也代表上傳的文件的最大值是50M)
2:Struts2對應的文件上傳的攔截器的限制
<interceptor-ref name="fileUpload"> <param name="maximumSize">52428800</param> </interceptor-ref>
這種方式是限制特定的Action的一種方式,當然她是在滿足第一種情況下才起作用的,換言之,這里的配置要小於第一種情況的設置才能起到對應的作用!
需要注意的是,攔截器的使用以及和第一種文件上傳之間的配合,情況如下(下面的代碼僅僅是事例代碼而已):
2-1:沒有攔截器的情況,僅第一種限制起作用
<action name="fileUpload" class="fileUploadAction" method="fileUpload"> </action>
2-2:僅使用默認的攔截器的情況,和2-1的效果一樣,它們兩個的本質是一樣的,因為Struts2會每個Action加入一個默認的攔截器,顯示說明與否皆可!
<action name="fileUpload" class="fileUploadAction" method="fileUpload"> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
2-3:僅使用文件上傳的攔截器的情況,第一種限制起作用,第二種限制也有效果,不過這種使用攔截器的方式是有問題的,這里僅僅使用了文件上傳的攔截器而已,導致數據信息的丟失!當實際上傳的文件大於攔截器的配置的時候,會報([WARN ] 2015-03-03 18:49:44 :File too large: fileUploadModel.upload "test.png" "upload_6e4dba7d_14be260bb68__7fe3_00000018.tmp" 11185361)不過程序會繼續的執行!
<action name="fileUpload" class="fileUploadAction" method="fileUpload"> <interceptor-ref name="fileUpload"> <param name="maximumSize">10485760</param> </interceptor-ref> </action>
2-4:先使用文件上傳的攔截器,再使用默認的攔截器的情況,第一種限制起作用,第二種限制也起作用,並且當實際上傳的文件的大小超過攔截器的限制時,程序會報錯([WARN ] 2015-03-03 18:53:30 :File too large: fileUploadModel.upload "test.png" "upload_53477faa_14bdea02616__7fef_00000008.tmp" 11185361)且程序會終止執行(調試的結果顯示沒有進入相應的Action類中)!
<action name="fileUpload" class="fileUploadAction" method="fileUpload"> <interceptor-ref name="fileUpload"> <param name="maximumSize">10485760</param> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
2-5:先使用默認的攔截器,再使用文件上傳的攔截器的情況,第一種限制起作用,第二種限制也起作用,不過當超過攔截器的限制時,程序會報錯([WARN ] 2015-03-03 18:58:30 :File too large: fileUploadModel.upload "test.png" "upload_53477faa_14bdea02616__7fef_00000008.tmp" 11185361)不過仍繼續的執行!
<action name="fileUpload" class="fileUploadAction" method="fileUpload"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="fileUpload"> <param name="maximumSize">10485760</param> </interceptor-ref> </action>
3:上傳文件的最大限制
文件上傳的最大值應<2G,無論前面兩項配置的是多大,當實際上傳的文件大小大於2G的時候就會出現如下圖的情況:
針對這個情況,我還不明白是什么原因引起的,如果有清楚的請告知一下,非常感謝!
三:對應的源碼的情況
第一種限制對應的關鍵性源碼(位置:commons-fileupload-1.2.2.jar包下\org\apache\commons\fileupload\FileUploadBase.java)
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 FileUploadBase.InvalidContentTypeException("the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is " + contentType); } InputStream input = ctx.getInputStream(); if (FileUploadBase.this.sizeMax >= 0L) { int requestSize = ctx.getContentLength(); if (requestSize == -1) input = new LimitedInputStream(input, FileUploadBase.this.sizeMax, FileUploadBase.this) { private final FileUploadBase val$this$0; protected void raiseError(long pSizeMax, long pCount) throws IOException { FileUploadException ex = new FileUploadBase.SizeLimitExceededException("the request was rejected because its size (" + pCount + ") exceeds the configured maximum" + " (" + pSizeMax + ")", pCount, pSizeMax); throw new FileUploadBase.FileUploadIOException(ex); } }; //看這里
else if ((FileUploadBase.this.sizeMax >= 0L) && (requestSize > FileUploadBase.this.sizeMax)) { throw new FileUploadBase.SizeLimitExceededException("the request was rejected because its size (" + requestSize + ") exceeds the configured maximum (" + FileUploadBase.this.sizeMax + ")", requestSize, FileUploadBase.this.sizeMax); } } String charEncoding = FileUploadBase.this.headerEncoding; if (charEncoding == null) { charEncoding = ctx.getCharacterEncoding(); } this.boundary = FileUploadBase.this.getBoundary(contentType); if (this.boundary == null) { throw new FileUploadException("the request was rejected because no multipart boundary was found"); } this.notifier = new MultipartStream.ProgressNotifier(FileUploadBase.this.listener, ctx.getContentLength()); this.multi = new MultipartStream(input, this.boundary, this.notifier); this.multi.setHeaderEncoding(charEncoding); this.skipPreamble = true; findNextItem(); }
第二種限制對應的關鍵性源碼(位置:struts2-core-2.3.1.2.jar包下\org\apache\struts2\interceptor\FileUploadInterceptor.java)
protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) { boolean fileIsAcceptable = false; if (file == null) { String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[] { inputName }, locale); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) LOG.warn(errMsg, new String[0]); } //看這里
else if ((this.maximumSize != null) && (this.maximumSize.longValue() < file.length())) { String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[] { inputName, filename, file.getName(), "" + file.length() }, locale); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) LOG.warn(errMsg, new String[0]); } else if ((!this.allowedTypesSet.isEmpty()) && (!containsItem(this.allowedTypesSet, contentType))) { String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[] { inputName, filename, file.getName(), contentType }, locale); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) LOG.warn(errMsg, new String[0]); } else if ((!this.allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(this.allowedExtensionsSet, filename))) { String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[] { inputName, filename, file.getName(), contentType }, locale); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) LOG.warn(errMsg, new String[0]); } else { fileIsAcceptable = true; } return fileIsAcceptable; }
四:參考的網絡資源如下
1)Struts2文件上傳大小限制相關
http://www.cnblogs.com/highriver/archive/2011/06/01/2065557.html
http://www.cnblogs.com/forlina/archive/2011/09/08/2171404.html
http://www.docin.com/p-633913742.html
2)Struts2攔截器相關
http://struts2.group.iteye.com/group/wiki/1397-deep-into-struts2-interceptors