Laravel9 线上共享服务器storage软链图片访问返回404问题
Laravel共享主机storage图片访问404问题排查与解决
问题场景
在cPanel类共享服务器部署Laravel项目,本地localhost环境下storage软链图片展示正常,部署后上传的图片访问返回404,已确认目录有读写权限,上传、文件写入功能正常。
部署前执行的缓存命令:
php artisan config:cache php artisan route:cache php artisan view:cache
手动通过PHP脚本创建的软链代码:
symlink('/home/cpanelUsername/project_folder/storage/app/public', '/home/cpanelUsername/public_html/www.domain.com/storage');

现有filesystem.php中public磁盘配置:
'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ],
上传业务代码:
$request->file('profile_image')->storeAs('public/profile', $filenametostore); $request->file('profile_image')->storeAs('public/profile/thumbnail', $smallThumbnail); $ThumbNail = 'storage/profile/thumbnail/'.$smallThumbnail; $this->createThumbnail($ThumbNail, 150, 93);
图片调用代码:
asset('storage/profile/'.$member->profile_image)

核心原因
- 手动写的软链绝对路径和网站实际web根目录不匹配,部分cPanel主机域名绑定的根目录不是
public_html/www.domain.com,路径偏差会导致软链指向无效位置 - 共享主机默认开启open_basedir安全限制,或Apache/Nginx未开启符号链接跟随规则,软链就算创建成功,web服务也无权读取软链目标目录的文件,直接返回404
- 提前执行了配置缓存,后续修改的APP_URL、路径配置不会生效,asset()生成的访问路径和实际文件路径不匹配
- 缩略图生成代码用了相对路径,脚本执行时工作目录不对会导致缩略图写入到错误位置,文件实际不存在
修复步骤
- 清理无效软链与缓存
进入cPanel文件管理器,删除网站入口根目录下已创建的无效storage软链接(注意不要删除项目内的storage实体目录),进入项目根目录执行命令清理所有缓存:
功能调试阶段不要提前开启各类缓存,避免配置修改不生效。php artisan config:clear php artisan route:clear php artisan view:clear php artisan cache:clear - 重新生成正确软链
不要手动写symlink绝对路径,优先使用Laravel内置命令生成软链,自动适配项目路径:
无SSH权限的话,在网站入口根目录创建临时PHP脚本,访问执行一次后立即删除:php artisan storage:link<?php require __DIR__.'/../project_folder/vendor/autoload.php'; $app = require_once __DIR__.'/../project_folder/bootstrap/app.php'; $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); use Illuminate\Support\Facades\Artisan; Artisan::call('storage:link'); echo Artisan::output(); - 开启web服务符号链接支持
绝大多数cPanel共享主机使用Apache,在网站根目录的.htaccess文件最顶部添加规则:
该规则适配绝大多数共享主机的安全限制,允许web服务读取和当前运行用户属主一致的符号链接。Options +SymLinksIfOwnerMatch - 修正缩略图路径
把原代码里的相对路径改成绝对路径,避免工作目录偏差导致文件写入错误位置:// 原代码 $ThumbNail = 'storage/profile/thumbnail/'.$smallThumbnail; // 替换为 $ThumbNail = storage_path('app/public/profile/thumbnail/'.$smallThumbnail); - 验证结果
上传一张新测试图片,直接在浏览器访问https://你的域名/storage/profile/测试图片文件名,能正常打开图片即修复完成,原asset()调用代码不需要修改即可正常加载图片。
内容的提问来源于stack exchange,提问作者Sarotobi
相关产品推荐
相关产品推荐

