文件上传时,文件太大会有几种被限制的情况
近期在维护一个项目时,商户有反馈,在新增用户时会直接卡住并报错,返回一个异常,应用层没有日志,最后排查出来是nginx限制了请求的最大值.
那么整个链路上都有哪些可能导致上传会被限制.比如前端页面表单输入数据较多,包含多个文本、多张图片,在数据未压缩的情况下,最终上传失败? 下面了梳理一下.
一个请求需要经过的路径:
nginx->servlet中间件->具体应用框架(springmvc,strust2)->内部rpc访问->数据库
下面这里汇总一下中间过程可能会导致限流的地方,以及需要调整的配置.
nginx
用nginx来做webserver的时,上传大文件时需要特别注意client_max_body_size这个参数,否则会中断在nginx的请求中是无法记录到访问的.
nginx 日志文件里会提示 send too large body:50746366(大概是50MB)
查看nginx的配置,进入:/usr/local/nginx/conf/nginx.conf
(具体名字和路径可能不一样)
client_max_body_size 20m; 需要调整,(如果不配置则默认是1M)
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
client_max_body_size 20m;
include upstream.conf;
limit_conn_zone $binary_remote_addr zone=one:10m;
tomcat
当服务器是Tomcat时,通过POST上传的文件大小的最大值为2M(2097152)
tomcat目录下的conf文件夹下,server.xml 文件中以下的位置中添加maxPostSize参数
<Connector port="8081" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="utf-8" maxPostSize="0" />
jetty
Jetty的默认值为200k,我们可以在配置内修改这个默认设置,修改JETTY_HOME/etc/jetty.xml,对maxFormContentSize重新赋值,-1表示不限制,正数值表示所允许的最大bytes:
jetty的参数文件 vim jetty.xml
<Configure id="Server" class="org.eclipse.jetty.server.Server">
添加
<Call name="setAttribute">
<Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
<Arg>2000000</Arg>
</Call>
<Call name="setAttribute">
<Arg>org.eclipse.jetty.server.Request.maxFormKeys</Arg>
<Arg>2000</Arg>
</Call>
springboot 限制
1. 内置tomcat
修改Spring Boot
内置Tomcat的maxPostsize
值,在application.yml
配置文件中添加以下内容
yaml 格式:
server:
tomcat:
max-http-post-size: -1
properties格式:
server.tomcat.max-http-post-size=-1
2.springmvc 设置文件上传大小限制
springboot 配置
Spring Boot 1.3 或之前的版本,配置:
multipart.maxFileSize = 100Mb
multipart.maxRequestSize=150Mb
Spring Boot 1.4 版本后配置更改为:
spring.http.multipart.maxFileSize = 100Mb spring.http.multipart.maxRequestSize = 150Mb
Spring Boot 2.0 之后的版本配置修改为:( Mb改为MB了)
spring.servlet.multipart.max-file-size = 100MB spring.servlet.multipart.max-request-size = 150MB
如果是想要不限制文件上传的大小,那么就把两个值都设置为-1
文档地址:docs.spring.io/spring-boot…
具体的版本:选择版本后进入 reference/html 举例:docs.spring.io/spring-boot…
老版本xml的配置
maxInMemorySize
: 此为阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件
maxUploadSize
: 一旦超过就上传失败!应该有异常处理器转发报错页面
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8">
<!--500*1024*1024 -->
<property name="maxUploadSize"><value>524288000</value></property>
<property name="maxInMemorySize"><value>4096</value></property>
</bean>
strust2 限制
一些老项目仍然使用的strust2的框架.
Struts2上传文件的默认大小限制是2M(2097152字节),可在struts配置文件里设置 上传文件的最大值struts.xml
<struts>
<!-- 设置常量 上传文件大小最大值,系统默认是2M,此设置为100M(1024*1024*100=104857600) -->
<constant name="struts.multipart.maxSize" value="104857600" />
</struts>
rpc框架限制
dubbo框架的限制
解决方案:
- 使用hessian协议进行传输 (参照dubbo 官网,或者搜索dubbo hessian )
- 将文件转换成byte[]继续使用dubbo协议(这种情况一般用于上传文件跟业务有关联)
当传输协议为:dubbo协议时 默认是8M(8388608) 单位字节 (1M=1048576)
当dubbo服务提供层向消费层传输大数据容量的对象时,会受到Dubbo的限制,报类似如下异常:
com.alibaba.dubbo.remoting.transport.AbstractCodec.checkPayload() ERROR
Data length too large: 11557050, max payload: 8388608
java.io.IOException: Data length too large: 11557050, max payload: 8388608
调整内容
1、 统一修改提供方的dubbo配置,
在dubbo.properties 中增加如下
dubbo.protocol.dubbo.payload=11557050(默认为8M,即8388608)
2、特殊dubbo修改提供方的dubbo配置:
<dubbo:protocol name="dubbo" port="${rmi.protocol.rmi.port}" payload = "104857600"/>
如果是使用dubbo协议的话,是不支持 file,inputStream 这种文件,流的传输的.
这种没有限制,具体可以看一下. Dubbo服务 上传文件解决方案以及Hessian协议
DB限制
超出了数据库中最大允许数据包默认配置值(mysql)
Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (16800061 > 16777216). You can change this value on the server by setting the max_allowed_packet’ variable.
修改DB的max_allowed_packet
值:
USE demo; set global max_allowed_packet = 310241024*10; # 改为30M show VARIABLES like '%max_allowed_packet%'; # 重启DB连接生效
Note:MySQL
中max_allowed_packet
的 默认配置:16777216 = 16 * 1024 * 1024
,即16M
参考文档
- Spring Boot配置内置Tomcat的maxPostSize值
- nginx 更改配置client_max_body_size nginx.conf 修改默认限制上传附件大小
- Dubbo限制大数据传输的解决方案
- dubbo(三)dubbo的文件上传
- Dubbo服务 上传文件解决方案以及Hessian协议
如果觉得文章对您有用,可以关注我的公众号 程序和猫 , 更加方便的交流.