文件上传时,文件太大会有几种被限制的情况

2,679 阅读2分钟

文件上传时,文件太大会有几种被限制的情况

​ 近期在维护一个项目时,商户有反馈,在新增用户时会直接卡住并报错,返回一个异常,应用层没有日志,最后排查出来是nginx限制了请求的最大值.

​ 那么整个链路上都有哪些可能导致上传会被限制.比如前端页面表单输入数据较多,包含多个文本、多张图片,在数据未压缩的情况下,最终上传失败? 下面了梳理一下.

一个请求需要经过的路径:

nginx->servlet中间件->具体应用框架(springmvc,strust2)->内部rpc访问->数据库

下面这里汇总一下中间过程可能会导致限流的地方,以及需要调整的配置.

nginx

用nginx来做webserver的时,上传大文件时需要特别注意client_max_body_size这个参数,否则会中断在nginx的请求中是无法记录到访问的.

nginx 日志文件里会提示 send too large body:50746366(大概是50MB)

image-20201112140322430

查看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:MySQLmax_allowed_packet 的 默认配置:16777216 = 16 * 1024 * 1024,即16M

参考文档

  1. Spring Boot配置内置Tomcat的maxPostSize值
  2. nginx 更改配置client_max_body_size nginx.conf 修改默认限制上传附件大小
  3. Dubbo限制大数据传输的解决方案
  4. dubbo(三)dubbo的文件上传
  5. Dubbo服务 上传文件解决方案以及Hessian协议

如果觉得文章对您有用,可以关注我的公众号 程序和猫 , 更加方便的交流.

在这里插入图片描述