今天给博客加了个头像上传裁剪功能,本来以为挺简单的,结果还是踩了个小坑。
需求很明确:上传一张头像,然后裁剪成几个常用尺寸。不算复杂,用的是 intervention/image 这个库来处理图片裁切。
代码写完本地测试没问题,一部署到服务器就不行了。上传之后图片就是生成不出来,也不报错,就是静默失败。
开始怀疑是代码问题。看了一圈上传逻辑,又看了裁切代码,感觉都没毛病。然后开始看日志,发现有一段:
Unable to retrieve file_size for file at location...
看到这个就有点懵,觉得是不是临时文件处理有问题。改了一版上传逻辑,不走框架的临时文件机制,直接从真实路径读内容再写入:
$contents = file_get_contents($file->getRealPath());
$disk->put($filename, $contents);
这样确实稳了一点,但还是没解决根本问题。
最后是怎么发现的呢?去看了一下服务器上目录的权限。
目标目录是 755,看起来没问题。但仔细一看所有者:root。而项目其他目录是 755 www。
问题就在这。755 的意思是所有者可写。如果 Web 服务用 www 用户跑,那它面对 755/root 的目录,其实是写不进去的。
这就是为什么"权限看着没问题",上传却一直失败。
解决也很朴素:
chown -R www:www [头像目录]
改完之后就好了,头像原图和各种尺寸都能正常生成。
这事让我想到,很多人排查上传失败会先看代码、看配置、看目录存不存在,但如果不搞清楚"Web 服务实际是哪个用户在跑文件",很容易在错误的方向上绕很久。
上传归根结底是个写文件的操作,最后还是得回到最原始的问题:这个进程有没有权限往这个目录里写东西。
博客名字:gankudadiz的个人小站
博客地址:https://blog.gankudadiz.com/
头像:https://blog.gankudadiz.com/avatar/avatar-128x128.jpg
博客介绍:记录coding与生活。<127.0.0.1 is where the heart is>