|
|
这两天在折腾老项目,前端同学反馈“xiuno图片无法上传”。一开始我以为是权限问题,结果一路排查下来,才发现这事儿背后有不少坑。这里把我的过程和一些可复用的思路记录一下,供还在维护 xiuno 的朋友参考。
先说最常见的两类问题:一是环境变动导致的上传失败,二是程序层面的限制拦截。环境这块,PHP 版本升级、Nginx/Apache 配置调整、服务器迁移、CDN 回源策略变化,都可能让原本好好的上传突然挂掉。尤其是 PHP8 以后,某些警告升级成错误,老代码里用到的函数或写法会直接中断。遇到这种“点上传没反应/报错码不稳定”的,第一步别猜,直接看服务端 error log 和 Nginx 的 access/error log,能少走很多弯路。
权限问题依旧是经典:upload、tmp、attach
目录的可写权限必须确认,别只看 chmod 777 就以为万事大吉,还要确认属主属组与 PHP 运行用户一致(比如 www-data 或 nginx)。SELinux/ACL 也可能“表面可写、实际被拦”。简单粗暴的验证方法:用一个最小化的 PHP 脚本 move_uploaded_file 到相同目录,排除框架干扰。
再说 PHP 配置层面的坑:post_max_size 和 upload_max_filesize 不一致、memory_limit 太小、max_file_uploads 限制触发,都会让大图或多图批量上传失败。还有 max_execution_time 在慢网或大图压缩时踩雷。推荐把 phpinfo 导出来对照,确认 FPM 与 CLI 用的是同一份 ini,不要在命令行测得好好的,线上却读
到另一套配置。很多人忽略了 user.ini 或者 vhost 里的 fastcgi_param PHP_VALUE 覆盖项,结果页面环境和你以为的不一样。
应用层也有一堆细节。xiuno 的上传通常会做 MIME 检查、后缀白名单、大小限制、以及简单的图像验证(getimagesize/exif_imagetype)。这里有几个典型雷点:
- 仅信任前端传的 Content-Type 导致被代理或浏览器异常时识别失败。
- exif 扩展缺失,exif_imagetype 不可用,回退逻辑没做好直接判失败。
- getimagesize 在遇到 WebP/HEIC 时返回异常,老版本 GD 不支持,Imagick 又没装。
- 文件名/后缀过滤过严,诸如 .jpeg 被当成不合规,或多后缀绕过被整治过头。
如果是“部分格式能传、部分不行”,优先检查 GD/Imagick 支持的格式列表和 php -m 扩展加载情况,然后看 xiuno 上传代码的类型判断分支。近几年移动端拍照容易出 HEIC/HEIF,很多老项目根本不认,最省事的办法是:前端在选择后直接用 canvas 转出 JPEG/WebP;后端兜底做一次格式转换(Imagick/ffmpeg 亦可),同时留好原图尺寸限制,避免内存炸裂。
说到内存,图片压缩和缩略图生成是大头。GD 处理超大分辨率(比如 8000x6000)很容易 memory_limit 顶不住。经验值:估算内存约为 宽×高×通道数×系数,RGBA 粗略按 5–6 倍字节算,留 2–3 倍安全冗余。策略上可以:
- 先用 getimagesize 读出尺寸,超过阈值先拒绝或等比缩到安全边界再进处理。
- 分辨率门槛与
质量上限分开配置,避免单图小但总像素极大导致内存峰值过高。
- 采用流式/分块读写,避免一次性把整图 decode 到内存;Imagick 可考虑使用 setResourceLimit、stripImageProfile 降低开销。
- 关闭不必要的 EXIF 保留与多次重采样,减少重复处理。
再看网络与反向代理。很多“明明本地好好的,上线就挂”的案例,最后发现是 Nginx 的
client_max_body_size 或者 proxy_request_buffering 搞的鬼。前者限制了请求体大小,超过就直接 413,后者在启用时会把大文件先缓存在磁盘,磁盘慢或满了就各种超时/断流。再配上后端 FPM 的 request_terminate_timeout、Nginx 的 proxy_read_timeout,如果压缩处理时间较长,很容易在边界条件下被误杀。排查思路:抓一次完整的上传请求,用 curl -F 复现,看返回码与响应头;Nginx error log 里如果出现 upstream sent too big header/body 或 client intended to send too large body,基本就指向配置了。对策就是对应地调大 client_max_body_size、fastcgi_buffer_*,并确保后端和前端反向代理链路上的限制一致。
还有一个被忽略的点是临时目录与磁盘配额。很多系统把 / |
|