PHP 的 post_max_size 和 upload_max_size 限制请求体大小,超限时PHP在Laravel路由前返回400/500;Nginx的client_max_body_size优先级最高,需同步配置;Laravel中间件可通过Content-Length头做细粒度拦截,但不可调用getContent()或all()。

PHP 本身限制 post_max_size 和 upload_max_filesize
Laravel 不会绕过 PHP 的底层限制,所有 POST 数据(包括 JSON body 和文件)都受这两个 ini 配置约束。如果请求体超限,PHP 在 Laravel 路由执行前就直接返回 400 或 500,你根本收不到请求——Request 对象都构建不出来。
常见错误现象:Client error: `POST xxx` resulted in a `400 Bad Request` response,但日志里没 Laravel 报错;或者 Nginx 返回 413 Request Entity Too Large(那是 Nginx 拦的,不是 PHP)。
- 检查当前值:
php -i | grep -E "(post_max_size|upload_max_filesize)" - 修改
php.ini后必须重启 PHP-FPM(或 Apache),仅 reload 不生效 -
post_max_size必须 ≥upload_max_filesize,否则大文件上传会静默失败 - 如果只传 JSON(无文件),
upload_max_filesize可设小些,但post_max_size才是真正管 API body 大小的
Laravel 中间件校验 Content-Length 请求头
PHP 层限制太粗,无法按路由区分策略(比如 /api/upload 允许 10MB,/api/login 只允许 10KB)。这时得在 Laravel 请求进入逻辑前做轻量拦截,靠中间件读取 Content-Length 头是最省资源的方式——不解析 body,不触发内存分配。
使用场景:对特定 API 端点做细粒度控制,避免恶意构造超大 JSON 导致内存暴涨或 OOM。
- 中间件里用
$request->header('Content-Length')获取字节数,转成 int 后比大小 - 注意:某些代理(如 Cloudflare)可能删除或改写
Content-Length,此时该值为 null,需 fallback 到后续校验 - 别在中间件里调
$request->getContent()或$request->all(),那会强制解析整个 body,失去“提前拦截”意义 - 示例判断:
if ($contentLength && $contentLength > 2 * 1024 * 1024) { abort(413, 'Payload too large'); }
FormRequest 验证器里的 max: 规则不适用于原始 body
max: 验证规则只作用于已解析后的字段值(比如 $request->input('data')),它对原始 JSON body、二进制流、未命名的 multipart 数据完全无效。很多人误以为加个 'body' => 'max:1024' 就能限制整个请求体,结果发现毫无作用。
性能影响:如果 body 已被解析(比如 Laravel 自动把 JSON 解成数组),再用 max: 校验字段长度,本质是 PHP 数组遍历 + 字符串 strlen,开销小;但前提是 body 已进来——而超限的请求根本到不了这步。
- JSON 接口可手动验证:
json_last_error() === JSON_ERROR_NONE,但无法限制总长度 - 上传文件走
file+mimes+max规则有效,因为 Laravel 会调用$_FILES信息(来自 PHP 上传机制) - 不要试图用
required|string|max:1000去约束整个 raw body,$request->getContent()不是验证器默认读取的源
Nginx/Apache 反向代理层也要同步设限
哪怕 PHP 和 Laravel 都设了限制,如果前端有 Nginx,它默认只允许 1MB 的请求体,超限直接返回 413,压根不转发给 PHP。这个层级的限制优先级最高,且无法被 Laravel 拦截或覆盖。
容易踩的坑:本地开发用 PHP 内置服务器没问题,一上生产环境就 413,查半天才发现是 Nginx 的 client_max_body_size 没配。
- Nginx 配置项:
client_max_body_size 20M;,放在http、server或location块中均可,越具体越优先 - Apache 用
LimitRequestBody 20971520(单位是字节) - Cloudflare 默认限制 100MB,但免费版对上传有额外限制,需确认是否启用了 Web Application Firewall 规则
- 修改后必须
nginx -t && nginx -s reload,配置语法错会导致整个服务不可用
事情说清了就结束。最常漏的是 Nginx 层和 PHP ini 的联动——改了 Laravel 配置却忘了 reload PHP-FPM,或者调大了 PHP 限制但 Nginx 还卡在 1MB,问题依旧。


















