Ubuntu+Nginx上Laravel7上传120MB文件报CannotWriteFileException
大文件上传异常排查指南
场景说明
在Ubuntu + Nginx环境下部署Laravel 7项目时,上传10MB以内文件流程正常,上传120MB文件时触发报错;已将php.ini中memory_limit、upload_max_filesize、post_max_size参数调整为640M,且已重启php-fpm、nginx服务,问题仍未解决。
排查解决步骤
- 补全Nginx层的请求体大小限制配置
Nginx默认拦截超过自身阈值的客户端请求,该限制独立于PHP的上传配置,是大文件上传问题最高发的漏配项。可在Nginx对应站点的server块、全局http块或上传接口对应的location块中,检查client_max_body_size参数,其默认值通常为1M,远低于120MB的上传需求,需调整为与PHP配置匹配的大小:
配置修改完成后,执行client_max_body_size 640M;nginx -t校验语法无误,重载Nginx服务即可生效。 - 校验临时目录的磁盘空间与读写权限
从日志记录可见,大体积的请求体、上游响应会被Nginx缓存到本地临时目录,临时目录异常会直接中断上传流程,需确认两项核心内容:- 磁盘剩余容量:Nginx接收到大文件上传请求时,会先将完整的请求内容写入本地临时文件,再转发给PHP-FPM处理,若临时目录所在分区剩余空间不足(至少需预留2倍于单文件上传大小的空闲空间),会直接导致写入失败、上传中断。可通过
df -h /var/lib/nginx命令查看对应分区的剩余容量。 - 目录读写权限:确认Nginx运行用户(通常为www-data)对
/var/lib/nginx/body、/var/lib/nginx/fastcgi目录拥有读写权限;同时确认PHP-FPM对自身配置的上传临时目录(默认路径为/tmp,可通过phpinfo输出的sys_temp_dir字段查看真实配置路径)拥有读写权限,权限不足会导致临时文件写入失败。
- 磁盘剩余容量:Nginx接收到大文件上传请求时,会先将完整的请求内容写入本地临时文件,再转发给PHP-FPM处理,若临时目录所在分区剩余空间不足(至少需预留2倍于单文件上传大小的空闲空间),会直接导致写入失败、上传中断。可通过
- 调整PHP与PHP-FPM的超时阈值
120MB的大文件上传受网络带宽影响,传输耗时远长于小文件,默认的超时参数会在文件未传输完成时中断服务流程:- 在php.ini中检查
max_execution_time(脚本最大执行时间,单位秒)、max_input_time(接收请求输入数据的最大等待时间,单位秒),建议调整到300以上,适配慢带宽场景下的大文件传输需求。 - 检查PHP-FPM对应站点的pool配置(路径通常为/etc/php/[对应PHP版本]/fpm/pool.d/下的站点配置文件)中的
request_terminate_timeout参数,默认值通常为60s,会在上传未完成时回收PHP进程,建议调整到300s以上。
- 在php.ini中检查
- 核对Laravel应用的存储目录配置
从错误日志可见,流程中尝试读取/var/www/servername/video/class/路径下的上传文件时报不存在,需确认两项内容:- 代码中配置的上传目标路径(如上述video/class目录)是否真实存在,若目录缺失,上传时会因无法创建写入文件导致流程失败。
- Nginx、PHP-FPM运行用户对项目的storage目录、自定义上传目录拥有完整读写权限,避免写入时触发权限错误。
参考错误日志
2021/01/21 21:11:51 [warn] 13069#13069: *1 a client request body is buffered to a temporary file /var/lib/nginx/body/0000000001, client: 92.47.198.158, server: servername, request: "POST /courseclass/17 HTTP/2.0", host: "servername", referrer: "https://servername/courseclass/17" 2021/01/21 21:11:53 [error] 13069#13069: *1 openat() "/var/www/servername/video/class/video_course_1611240590.mp4" failed (2: No such file or directory), client: 92.47.198.158, server: servername, request: "GET /video/class/video_course_1611240590.mp4 HTTP/2.0", host: "servername", referrer: "https://servername/watch/course/6" 2021/01/21 21:11:54 [error] 13069#13069: *1 openat() "/var/www/servername/video/class/video_course_1611240590.mp4" failed (2: No such file or directory), client: 92.47.198.158, server: servername, request: "GET /video/class/video_course_1611240590.mp4 HTTP/2.0", host: "servername", referrer: "https://servername/watch/course/6" 2021/01/21 21:41:18 [error] 13069#13069: *8 openat() "/var/www/servername/images/light.jpg" failed (2: No such file or directory), client: 92.47.149.211, server: servername, request: "GET /images/light.jpg HTTP/2.0", host: "servername", referrer: "https://servername/" 2021/01/21 21:41:21 [error] 13069#13069: *8 openat() "/var/www/servername/images/light.jpg" failed (2: No such file or directory), client: 92.47.149.211, server: servername, request: "GET /images/light.jpg HTTP/2.0", host: "servername", referrer: "https://servername/" 2021/01/21 21:49:53 [warn] 13069#13069: *10 an upstream response is buffered to a temporary file /var/lib/nginx/fastcgi/3/00/00/0000000003 while reading upstream, client: 92.47.198.158, server: servername, request: "POST /courseclass/17 HTTP/2.0", upstream: "fastcgi://unix:/var/run/php/servername.sock:", host: "servername", referrer: "https://servername/courseclass/17"
内容的提问来源于stack exchange,提问作者Abylay Omar
相关产品推荐
相关产品推荐

