上傳文件的大小限制 專題

tomcat nginx默認的post大小限制
執行大文件上傳,或者,大數據量提交時,當提交的數據大小超過必定限制時,發現後臺從request取值的代碼request.getParameter("message")返回值爲null,緣由是由於服務器對於提交的post請求的大小有必定的限制

tomcat:默認大小2097152,當maxPostSize=0時,不限制;maxPostSize=20971520時,爲20M
nginx:默認的最大請求body大小爲8m,修改設置client_max_body_size=100m;
resin:沒有發現默認限制請求大小的地方! html

Tomcat:前端

server.tomcat.max-connections=0 # Maximum number of connections that the server accepts and processes at any given time.
server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header. server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content. server.tomcat.max-threads=0 # Maximum number of worker threads. server.tomcat.min-spare-threads=0 # Minimum number of worker threads.

undertow:java

server.undertow.buffer-size= # Size of each buffer, in bytes.
server.undertow.direct-buffers= # Whether to allocate buffers outside the Java heap. server.undertow.io-threads= # Number of I/O threads to create for the worker. server.undertow.eager-filter-init=true # Whether servlet filters should be initialized on startup. server.undertow.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content. server.undertow.worker-threads= # Number of worker threads.

https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/linux

 

Spring MVC上傳文件原理和resolveLazily說明

問題:使用Spring MVC上傳大文件,發現從頁面提交,到進入後臺controller,時間很長。懷疑是文件上傳完成後,才進入。因爲在HTTP首部自定義了「Token」字段用於權限校驗,Token的有效時間很短,所以上傳大文件時,就會驗證Token失敗。nginx

示例代碼:git

前端:github

<form action="upload" enctype="multipart/form-data" method="post">
        <table>
            <tr>
                <td>文件描述:</td>
                <td><input type="text" name="description"></td>
            </tr>
            <tr>
                <td>請選擇文件:</td>
                <td><input type="file" name="file"></td>
            </tr>
            <tr>
                <td><input type="submit" value="上傳"></td>
            </tr>
        </table>
</form>

 

controller:web

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, 
        @RequestParam("description") String description, 
        @RequestParam("file") MultipartFile file) throws Exception {
    System.out.println("enter controller.");
    }

springmvc-config.xml配置:spring

  <bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <property name="maxUploadSize">  
            <value>524288000</value>  
        </property>  
        <property name="defaultEncoding">
            <value>UTF-8</value>
        </property>
    </bean>

Spring MVC上傳文件使用了Commons FileUpload類庫,即 CommonsMultipartResolver 使用 commons Fileupload 來處理 multipart 請求,將Commons FileUpload的對象轉換成了Spring MVC的對象。shell

那若是直接使用Commons FileUpload來進行文件上傳下載呢?

示例代碼:

protected void doPost(HttpServletRequest request,
                    HttpServletResponse response) throws ServletException, IOException {
                        System.out.println("enter servlet");
        }

發現從頁面提交,很快就進入了servlet。

既然Spring也是使用了Commons FileUpload類庫,但爲何差異這麼大呢?Spring在轉換過程當中作了什麼其餘操做呢?

查看源碼,或者直接看(https://www.cnblogs.com/tengyunhao/p/7670293.html)

發現 有個resolveLazily 是判斷是否要延遲解析文件(經過XML能夠設置)。當 resolveLazily 爲 flase 時,會當即調用 parseRequest() 方法對請求數據進行解析,而後將解析結果封裝到 DefaultMultipartHttpServletRequest 中;而當 resolveLazily 爲 true 時,會在 DefaultMultipartHttpServletRequest 的 initializeMultipart() 方法調用 parseRequest() 方法對請求數據進行解析,而 initializeMultipart() 方法又是被 getMultipartFiles() 方法調用,即當須要獲取文件信息時纔會去解析請求數據,這種方式用了懶加載的思想。

再次修改代碼:

一、在springmvc-config.xml增長一個配置resolveLazily,設置true;

二、將controller方法中將@RequestParam("file") MultipartFile file註釋

 

再次測試,發現仍是不對。。增長打印日誌後發現:

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, 
        @RequestParam("description") String description, 
        /*@RequestParam("file") MultipartFile file*/) throws Exception {
    System.out.println("enter controller.");
     System.out.println(request.getHeader("Accept"));
     System.out.println(request.getParam("description"));
    }

第1,2條日誌很快打印,第3條日誌還是文件上傳完後纔打印。簡單分析下,應該是後臺一直在接收數據,HTTP首部很快就能獲取到並解析出來(首部和正文之間有一個空行),但請求正文部分必須在請求數據徹底接收後才能解析,所以線程一直阻塞直到數據接收完成纔打印第3條日誌。所以解決方案是,把controller函數中的@RequestParam("description") String description也註釋掉,這樣頁面提交後,會當即進入controller中。

 

總結下最終的解決方案:

一、springmvc-config.xml增長一項配置:

<property name="resolveLazily ">
            <value>true</value>
        </property>

二、在controller的方法參數中,不能附加請求參數,應在函數中本身解析參數。

 

https://blog.csdn.net/smithallenyu/article/details/80515296

 

#org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1491511) exceeds the configured maximum (1048576)
spring.http.multipart.max-request-size=1MB

若是上傳文件大於1MB,會報錯:
配置:

#upload
#org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1491511) exceeds the configured maximum (1048576)
spring.http.multipart.max-request-size=1MB
#org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
spring.http.multipart.max-file-size=100MB
# Maximum size, in bytes, of the HTTP post content。this configuration maybe not needed
server.tomcat.max-http-post-size=1

報錯信息:

2018-05-08 13:46:43.090 ERROR 13780 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1491511) exceeds the configured maximum (1048576)] with root cause

org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1491511) exceeds the configured maximum (1048576)
    at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:805) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:256) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:280) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.parseParts(Request.java:2869) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.parseParameters(Request.java:3216) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.getParameter(Request.java:1137) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:75) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

 

#org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
spring.http.multipart.max-file-size=100MB

若是上傳文件大於1MB,則會報錯:
配置:

#upload
#org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1491511) exceeds the configured maximum (1048576)
spring.http.multipart.max-request-size=100MB
#org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
spring.http.multipart.max-file-size=1MB
# Maximum size, in bytes, of the HTTP post content。this configuration maybe not needed
server.tomcat.max-http-post-size=1

報錯信息:

2018-05-08 13:51:05.533 ERROR 1616 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.] with root cause

org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
    at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl$1.raiseError(FileUploadBase.java:630) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.checkLimit(LimitedInputStream.java:76) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:135) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at java.io.FilterInputStream.read(FilterInputStream.java:107) ~[na:1.8.0_144]
    at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:98) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:68) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:293) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.parseParts(Request.java:2869) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.parseParameters(Request.java:3216) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.Request.getParameter(Request.java:1137) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:75) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.27.jar:8.5.27]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]


從上面看,tomcat的配置好像並無什麼用:

# Maximum size, in bytes, of the HTTP post content。this configuration maybe not needed
server.tomcat.max-http-post-size=1

spring boot 版本:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>

DEMO:
https://github.com/helloworldtang/spring-boot-cookbook/tree/master/learning-demo/src/main/resources

 

Is there a maximum file size that spring boot can handle in a MultipartFile upload process.
 maxFileSize  and max-request-size in the property.
https://stackoverflow.com/questions/34177873/max-limit-of-multipartfile-in-spring-boot

# MULTIPART (MultipartProperties)
spring.servlet.multipart.enabled=true # Whether to enable support of multipart uploads.
spring.servlet.multipart.file-size-threshold=0 # Threshold after which files are written to disk. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.
spring.servlet.multipart.location= # Intermediate location of uploaded files.
spring.servlet.multipart.max-file-size=1MB # Max file size. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.
spring.servlet.multipart.max-request-size=10MB # Max request size. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.
spring.servlet.multipart.resolve-lazily=false # Whether to resolve the multipart request lazily at the time of file or parameter access.
    @Bean  
    public MultipartConfigElement multipartConfigElement() {  
        MultipartConfigFactory factory = new MultipartConfigFactory();  
        //單個文件最大  
        factory.setMaxFileSize("10240KB"); //KB,MB  
        /// 設置總上傳數據總大小  
        factory.setMaxRequestSize("102400KB");  
        return factory.createMultipartConfig();  
    }  

 

To upload files with Servlet containers, you need to register a MultipartConfigElement class (which would be <multipart-config> in web.xml). Thanks to Spring Boot, everything is auto-configured for you!

The multipart settings are constrained as follows:

spring.http.multipart.max-file-size is set to 128KB, meaning total file size cannot exceed 128KB.

spring.http.multipart.max-request-size is set to 128KB, meaning total request size for a multipart/form-data cannot exceed 128KB.

https://spring.io/guides/gs/uploading-files/

Servlet容器的限制 【這個配置好像不重要,爲何呢?】:
Tomcat:

server.tomcat.max-connections=0 # Maximum number of connections that the server accepts and processes at any given time.
server.tomcat.max-http-header-size=0 # Maximum size, in bytes, of the HTTP message header.
server.tomcat.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content.
server.tomcat.max-threads=0 # Maximum number of worker threads.
server.tomcat.min-spare-threads=0 # Minimum number of worker threads.

undertow:

server.undertow.buffer-size= # Size of each buffer, in bytes.
server.undertow.direct-buffers= # Whether to allocate buffers outside the Java heap.
server.undertow.io-threads= # Number of I/O threads to create for the worker.
server.undertow.eager-filter-init=true # Whether servlet filters should be initialized on startup.
server.undertow.max-http-post-size=0 # Maximum size, in bytes, of the HTTP post content.
server.undertow.worker-threads= # Number of worker threads.

https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/

 

大文件上傳失敗緣由之:Tomcat HttpPost超過大小和超時

應該是Tomcat或者Nginx的配置中限制了HttpPost的大小。因而我
Nginx中限制請求大小的地方是以下的client_max_body_size,咱們圖方便,直接分3000m,應該足矣:

      location /app {
            proxy_pass        http://server_name;
            client_max_body_size  3000m;
            access_log off;
        }

Tomcat則是在server.xml中的connector元素中添加:maxPostSize=」 」 ;「 」中填你須要限制到的大小,如「0」爲不限制。缺省這個參數,就會是2m.
因此應該是這裏出了問題。因而我添加一行maxPostSize=」0″:

 <Connector port="8038" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8028" URIEncoding="UTF-8"
               maxThreads="1000"
               maxPostSize="0"
               minSpareThreads="25" maxSpareThreads="75"  
               acceptCount="200"  />

上傳仍是失敗。

由於HttpPost不只是大小會限制,還會有時間限制。雖然你能夠上傳了,但你在connectionTimeout的限制時間內不能傳完,鏈接也會斷開的。

因此再將它修改以下,原先的connectionTimeout時間是「20000」,可是注意,單位是毫秒啊……因而我把它加到」2000000「,有半小時以上,足矣吧:

 <Connector port="8038" protocol="HTTP/1.1" 
               connectionTimeout="2000000" 
               redirectPort="8028" URIEncoding="UTF-8"
               maxThreads="1000"
               maxPostSize="0"
               minSpareThreads="25" maxSpareThreads="75"  
               acceptCount="200"  />

實測成功。
https://blog.csdn.net/sw_magic/article/details/16988457

spring-boot上傳文件MultiPartFile獲取不到文件問題解決
1.現象是在spring-boot里加入commons-fileupload jar而且配置了mutilPart的bean,在upload的POST請求後,發現multipartRequest.getFiles("file")=null,有點奇怪,查了文檔資料才解決。

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
       <property name="maxUploadSize" value="104857600"/>  
       <property name="maxInMemorySize" value="4096"/>  
</bean>  

2.緣由是:spring-boot自帶的org.springframework.web.multipart.MultipartFile
和Multipart產生衝突,若是同時使用了MultipartResolver 和ServletFileUpload,就會在iter.hasNext()返回false.而後整個循環就跳出去了。
整個問題產生的緣由是Spring框架先調用了MultipartResolver 來處理http multi-part的請求。這裏http multipart的請求已經消耗掉。
後面又交給ServletFileUpload ,那麼ServletFileUpload 就獲取不到相應的multi-part請求。
所以將multipartResolve配置去除,問題就解決了。

http://www.cnblogs.com/panxuejun/p/7476192.html

Tips:關於multipartResolver
Spring上傳文件,圖片,以及常見的問題

1. 在工程依賴庫下添加文件上傳jar包
  commons-fileupload-1.2.2.jar
  commons-io-2.4.jar

2.在springMVC配置文件中配置視圖解析multipartResolver 

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="5000000" />
        <property name="defaultEncoding" value="UTF-8" />
</bean>

這裏有個問題須要注意一下,Bean 的id必須爲multipartResolver,由於在項目初始化的時候,Spring容器會經過這個id來進行注入,下面是Spring源碼:

public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
/** MultipartResolver used by this servlet */
    private MultipartResolver multipartResolver;
/*
   省略一大堆代碼 
*/
/**
     * Initialize the MultipartResolver used by this class.
     * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
     * no multipart handling is provided.
     */
    private void initMultipartResolver(ApplicationContext context) {
        try {
            this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
            }
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Default is no multipart resolver.
            this.multipartResolver = null;
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
                        "': no multipart request handling provided");
            }
        }
    }

接下來,咱們測試一下若是寫錯以後會報什麼錯誤

 

上面只是DEBUG, 查看源碼就會知道會DEBUG輸出這一句,
下面是具體報的錯誤:預期的MultipartHttpServletRequest:是否配置了MultipartResolver?
Expected MultipartHttpServletRequest:is a MultipartResolver configured

下面依次是jsp代碼和後臺實現上傳的java代碼:

<form id="userForm" name="userForm" method="post"
        action="${pageContext.request.contextPath }/user/useraddsave.html"
        enctype="multipart/form-data">
            <div>
                <label for="a_idPicPath">證件照:</label> <input type="file"
                    name="a_idPicPath" id="a_idPicPath" /> <font color="red"></font>
            </div>
            <div class="providerAddBtn">
                <input type="button" name="add" id="add" value="保存"> <input
                    type="button" id="back" name="back" value="返回">
            </div>
</form>

 

//保存新增用戶信息
    @RequestMapping(value="/useraddsave.html",method=RequestMethod.POST)
    public String addUserSave(User user,HttpServletRequest request,@RequestParam(value="a_idPicPath",required=false) MultipartFile multipartFile){
        
        if(!multipartFile.isEmpty()){
            String path = "/statics"+File.separator+"upload"; //文件或者圖片上傳到的位置
            String oldName = multipartFile.getOriginalFilename(); //上傳的文件名
            String prefix = FilenameUtils.getExtension(oldName); //文件的後綴名
            int maxSize =5000000;
            if(multipartFile.getSize()<maxSize){
                if(prefix.equalsIgnoreCase("jpg")|| prefix.equalsIgnoreCase("png")){
                    String fileName = System.currentTimeMillis()+RandomUtils.nextInt(1000000)+"_Personal."+prefix; // 爲避免文件名同樣隨機生成的文件名保存在服務器
                    File targetFile = new File(path,fileName);
                    if(!targetFile.exists()){
                        targetFile.mkdirs();
                    }
                    try {
                        multipartFile.transferTo(targetFile); //開始上傳
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        request.setAttribute("uploadFileError", "上傳出現異常,上傳失敗");
                    }
                    String idPicPath= path+File.separator+fileName;
                    user.setIdPicPath(idPicPath);
                    user.setCreationDate(new Date());
                    userService.add(user);
                    return "redirect:/user/userlist.html";
                } else {
                    request.setAttribute("uploadFileError", "文件格式錯誤,上傳失敗");
                }
            } else {
                request.setAttribute("uploadFileError", "文件太大,上傳失敗");
            }
        }  
        return "useradd";//新增失敗返回到useradd.jsp
    }

方法須要添加參數 @RequestParam(value="a_idPicPath",required=false) MultipartFile multipartFile




http://www.cnblogs.com/gudu1/p/7515668.html

tomcat nginx默認的post大小限制
執行大文件上傳,或者,大數據量提交時,當提交的數據大小超過必定限制時,發現後臺從request取值的代碼request.getParameter("message")返回值爲null,緣由是由於服務器對於提交的post請求的大小有必定的限制

tomcat:默認大小2097152,當maxPostSize=0時,不限制;maxPostSize=20971520時,爲20M
nginx:默認的最大請求body大小爲8m,修改設置client_max_body_size=100m;
resin:沒有發現默認限制請求大小的地方!

tomcat:maxPostSize

The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing.
The limit can be disabled by setting this attribute to a value less than or equal to 0. If not specified, this attribute is set to 2097152 (2 megabytes).

Nginx的"413 request entiry too large"

tomcat返回400

tomcat請求端口都加上maxPostSize="0"

tomcat默認參數是爲開發環境制定,而非適合生產環境,尤爲是內存和線程的配置,默認都很低,容易成爲性能瓶頸。

 http://www.cnblogs.com/sunxucool/archive/2013/07/30/3225812.html

maxPostSize

The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The limit can be disabled by setting this attribute to a value less than or equal to 0. If not specified, this attribute is set to 2097152 (2 megabytes).

maxSavePostSize

The maximum size in bytes of the POST which will be saved/buffered by the container during FORM or CLIENT-CERT authentication. For both types of authentication, the POST will be saved/buffered before the user is authenticated. For CLIENT-CERT authentication, the POST is buffered for the duration of the SSL handshake and the buffer emptied when the request is processed. For FORM authentication the POST is saved whilst the user is re-directed to the login form and is retained until the user successfully authenticates or the session associated with the authentication request expires. The limit can be disabled by setting this attribute to -1. Setting the attribute to zero will disable the saving of POST data during authentication . If not specified, this attribute is set to 4096 (4 kilobytes).

 

acceptCount

The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.

 

maxSpareThreads

The maximum number of unused request processing threads that will be allowed to exist until the thread pool starts stopping the unnecessary threads. The default value is 50.

maxThreads

The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200.

minSpareThreads

The number of request processing threads that will be created when this Connector is first started. The connector will also make sure it has the specified number of idle processing threads available. This attribute should be set to a value smaller than that set for maxThreads. The default value is 4.

http://tomcat.apache.org/tomcat-5.5-doc/config/http.html

以前我覺得是method=post的問題,刪除 method=post 就行了,實際上是請求變成了get因此好了,今天才發現是 server.xml 裏面有一個設置在做怪!

刪掉這兩項就行了!

上網查了一下 maxPostSize 和 maxSavePostSize 是設置最大的表單長度的,給我設成1了!結果post表單沒了!

http://blog.csdn.net/nsrainbow/article/details/8948092

 

 

tomcat內存優化

linux修改TOMCAT_HOME/bin/catalina.sh,在前面加入

JAVA_OPTS="-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx1024m -Duser.timezone=Asia/Shanghai"

windows修改TOMCAT_HOME/bin/catalina.bat,在前面加入

set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx1024m

最大堆內存是1024m,對於如今的硬件仍是偏低,實施時,仍是按照機器具體硬件配置優化。

 

tomcat 線程優化

<Connector port="80" protocol="HTTP/1.1" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700" connectionTimeout="20000" redirectPort="8443" />

maxThreads="600"       ///最大線程數 minSpareThreads="100"///初始化時建立的線程數 maxSpareThreads="500"///一旦建立的線程超過這個值,Tomcat就會關閉再也不須要的socket線程。 acceptCount="700"//指定當全部可使用的處理請求的線程數都被使用時,能夠放處處理隊列中的請求數,超過這個數的請求將不予處理

 

這裏是http connector的優化,若是使用apache和tomcat作集羣的負載均衡,而且使用ajp協議作apache和tomcat的協議轉發,那麼還須要優化ajp connector。

<Connector port="8009" protocol="AJP/1.3" maxThreads="600" minSpareThreads="100" maxSpareThreads="500" acceptCount="700" connectionTimeout="20000" redirectPort="8443" />

 

因爲tomcat有多個connector,因此tomcat線程的配置,又支持多個connector共享一個線程池。

首先。打開/conf/server.xml,增長

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="20" maxIdleTime="60000" />

最大線程500(通常服務器足以),最小空閒線程數20,線程最大空閒時間60秒。

 

而後,修改<Connector ...>節點,增長executor屬性,executor設置爲線程池的名字:

<Connector executor="tomcatThreadPool" port="80" protocol="HTTP/1.1" connectionTimeout="60000" keepAliveTimeout="15000" maxKeepAliveRequests="1" redirectPort="443" />

能夠多個connector公用1個線程池,因此ajp connector也一樣能夠設置使用tomcatThreadPool線程池。

 

禁用DNS查詢

當web應用程序向要記錄客戶端的信息時,它也會記錄客戶端的IP地址或者經過域名服務器查找機器名 轉換爲IP地址。

DNS查詢須要佔用網絡,而且包括可能從不少很遠的服務器或者不起做用的服務器上去獲取對應的IP的過程,這樣會消耗必定的時間。

修改server.xml文件中的Connector元素,修改屬性enableLookups參數值: enableLookups="false"

若是爲true,則能夠經過調用request.getRemoteHost()進行DNS查詢來獲得遠程客戶端的實際主機名,若爲false則不進行DNS查詢,而是返回其ip地址

 

 

設置session過時時間

conf\web.xml中經過參數指定:

    <session-config> <session-timeout>180</session-timeout> </session-config> 單位爲分鐘。

 

Apr插件提升Tomcat性能

Tomcat可使用APR來提供超強的可伸縮性和性能,更好地集成本地服務器技術.

APR(Apache Portable Runtime)是一個高可移植庫,它是Apache HTTP Server 2.x的核心。APR有不少用途,包括訪問高級IO功能(例如sendfile,epoll和OpenSSL),OS級別功能(隨機數生成,系統狀態等等),本地進程管理(共享內存,NT管道和UNIX sockets)。這些功能可使Tomcat做爲一個一般的前臺WEB服務器,能更好地和其它本地web技術集成,整體上讓Java更有效率做爲一個高性能web服務器平臺而不是簡單做爲後臺容器。

在產品環境中,特別是直接使用Tomcat作WEB服務器的時候,應該使用Tomcat Native來提升其性能 

要測APR給tomcat帶來的好處最好的方法是在慢速網絡上(模擬Internet),將Tomcat線程數開到300以上的水平,而後模擬一大堆併發請求。 若是不配APR,基本上300個線程狠快就會用滿,之後的請求就只好等待。可是配上APR以後,併發的線程數量明顯降低,從原來的300可能會立刻降低到只有幾十,新的請求會毫無阻塞的進來。 在局域網環境測,就算是400個併發,也是一瞬間就處理/傳輸完畢,可是在真實的Internet環境下,頁面處理時間只佔0.1%都不到,絕大部分時間都用來頁面傳輸。若是不用APR,一個線程同一時間只能處理一個用戶,勢必會形成阻塞。因此生產環境下用apr是很是必要的。

複製代碼
(1)安裝APR tomcat-native apr-1.3.8.tar.gz 安裝在/usr/local/apr #tar zxvf apr-1.3.8.tar.gz #cd apr-1.3.8 #./configure;make;make install apr-util-1.3.9.tar.gz 安裝在/usr/local/apr/lib #tar zxvf apr-util-1.3.9.tar.gz #cd apr-util-1.3.9 #./configure --with-apr=/usr/local/apr ----with-java-home=JDK;make;make install #cd apache-tomcat-6.0.20/bin #tar zxvf tomcat-native.tar.gz #cd tomcat-native/jni/native #./configure --with-apr=/usr/local/apr;make;make install (2)設置 Tomcat 整合 APR 修改 tomcat 的啓動 shell (startup.sh),在該文件中加入啓動參數: CATALINA_OPTS="$CATALINA_OPTS -Djava.library.path=/usr/local/apr/lib" 。 (3)判斷安裝成功: 若是看到下面的啓動日誌,表示成功。 2007-4-26 15:34:32 org.apache.coyote.http11.Http11AprProtocol init
複製代碼

 

參考 http://blog.sina.com.cn/s/blog_417b97470100glmi.html

       http://datadig.blog.163.com/blog/static/171229928201082075946726/

 

http://www.cnblogs.com/ggjucheng/archive/2013/04/16/3024731.html

相關文章
相關標籤/搜索