Laravel部署至生产服务器后文件上传失败问题咨询
问题核心说明
php artisan serve 启动的服务使用当前执行命令的系统用户权限运行,而Apache模式下PHP以web服务专属用户身份运行(Debian/Ubuntu 系为www-data,CentOS/RHEL 系为apache),两种运行模式的权限逻辑完全不同,你遇到的本地域名访问、生产环境访问双端上传失败问题,和贴出的APP_URL配置无关,基本是目录权限、配置漏项导致的。
排查修复检查清单
按优先级从上到下排查,90%的场景前两步就能解决问题。
- 第一优先级:修正目录属主与权限
不要直接给目录开777权限(不安全且不符合生产规范),进入项目根目录执行对应命令:
如果你用的是DigitalOcean默认的Ubuntu/Debian镜像:
如果你用的是CentOS/RHEL系统,把上面命令里的# 给web运行用户分配storage和缓存目录的属主权限 chown -R www-data:www-data storage/ bootstrap/cache/ # 目录设755权限、文件设644权限的标准安全配置 find storage/ -type d -exec chmod 755 {} \; find storage/ -type f -exec chmod 644 {} \; chmod -R 755 bootstrap/cache/www-data换成apache即可。
补充说明:Laravel默认不会自动递归创建多级嵌套上传目录,如果你代码里写入的路径存在未创建的子目录,要么提前手动创建,要么在config/filesystems.php对应磁盘的配置项中加'create_dir' => true开启自动建目录。你之前手动创建子目录后依然失败,基本是因为创建目录时用的是root或其他非web运行用户,目录属主不对,Apache没有写入权限。
如果是CentOS/RHEL开了SELinux的场景,还要额外执行命令给目录加web写入上下文:chcon -R -t httpd_sys_rw_content_t storage/ chcon -R -t httpd_sys_rw_content_t bootstrap/cache/ - 第二优先级:校验public存储软链与Apache配置
如果你使用public磁盘存储可对外访问的上传文件,先重新生成软链避免旧链接指向错误路径:
同时检查对应Apache虚拟主机配置:# 删除可能存在的失效旧软链 rm -f public/storage # 重新生成storage到public目录的软链 php artisan storage:link- 确认
DocumentRoot指向项目的public目录,而非项目根目录(配置错误不仅会导致上传异常,还会泄露.env等敏感文件) - 站点目录配置中要加上
Options FollowSymLinks允许软链生效,同时开启AllowOverride All保证Laravel自带的.htaccess重写规则正常运行
- 确认
- 第三优先级:校验PHP与Livewire上传配置
Apache加载的php.ini配置文件和命令行(php artisan)加载的不是同一个文件,不要改错路径。Ubuntu下Apache的php.ini路径一般为/etc/php/[你的PHP版本号]/apache2/php.ini,修改以下参数:
修改完成后执行file_uploads = On upload_max_filesize = 20M ; 按实际业务需求调整大小 post_max_size = 25M ; 数值必须大于upload_max_filesize max_file_uploads = 20 upload_tmp_dir = /tmp ; 不要注释该配置,指定的临时目录必须存在且对web运行用户可写systemctl restart apache2重启服务生效。
再检查config/livewire.php中的temporary_file_upload配置项,确认临时文件上传目录可写、关联的磁盘配置没有写错路径。 - 第四优先级:定位具体报错
你现在看到的通用报错是因为APP_DEBUG=false屏蔽了详细错误信息,临时把.env中的APP_DEBUG改为true,执行php artisan config:clear清掉配置缓存后再触发一次上传,就能看到具体的错误原因(是权限不足、路径不存在还是大小超限),排查完成后记得把debug改回false,生产环境执行php artisan config:cache重新缓存配置。
功能验证方法
所有配置改完后,不用直接走前端上传测试,先在项目根目录执行php artisan tinker进入命令行交互,运行以下代码测试存储写入能力:
Storage::disk('你代码里用的存储磁盘名,默认是public')->put('test.txt', 'test upload content');
如果代码执行成功返回文件路径,说明服务端存储配置完全正常,问题出在Livewire前端请求或临时文件配置上;如果执行直接报错,根据报错信息对应修复即可。
内容的提问来源于stack exchange,提问作者ThurstonLevi
相关产品推荐
相关产品推荐

