本文详解 laravel 中使用 `storage:link` 后仍无法通过 `asset()` 加载 `storage/app/public/` 下图片的常见原因,并提供完整解决方案,包括路径修正、url 生成逻辑、权限检查及安全建议。
在 Laravel 中,将用户上传或 Seeder 生成的图片存入 storage/app/public/ 目录(如 storage/app/public/users/xxx.jpg)是标准做法,但直接用 asset('storage/users/xxx.jpg') 加载会失败——这不是路径写错,而是对 Laravel 资源机制的理解偏差。
Laravel 的 asset() 辅助函数仅支持从 public/ 目录及其子目录中引用静态资源(如 CSS、JS、图片)。它不会穿透到 storage/ 目录,即使你已执行 php artisan storage:link 创建了符号链接(该命令本质是将 public/storage → storage/app/public),正确的访问路径也必须以 storage/ 开头(即 public/storage/...),而非 storage/...。
你当前的 img 标签:
@@##@@image) }}" ...>
生成的 URL 是类似 /storage/users/123.jpg

// ❌ 错误:faker->image() 写入绝对路径,且含 'storage/app/public/'
'image' => $this->faker->image('storage/app/public/users', 140, 180, null, false),
// ✅ 正确:只指定相对子路径(Laravel 自动存入 storage/app/public/)
'image' => $this->faker->image('users', 140, 180, null, false), // 生成如: users/abc.jpg这样数据库中存储的 image 字段值就是 users/abc.jpg,不带 storage/app/public/ 前缀。
@use('Illuminate\Support\Facades\Storage')
@@##@@image) }}"
class="avatar avatar-sm me-3 border-radius-lg"
alt="user avatar">✅ Storage::url() 会自动拼接为 /storage/users/abc.jpg(对应 public/storage/users/abc.jpg 符号链接),且支持云存储驱动无缝切换。
? 补充:若坚持用 asset(),需手动补全 storage/ 前缀,且确保 $user->image 不含重复路径:
运行以下命令确认链接存在且可读:
ls -la public/storage # 应输出类似:storage -> ../storage/app/public
同时检查 storage/app/public/users/ 下图片是否存在,且 Web 服务器(Nginx/Apache)有读取权限。
问题核心在于混淆了 asset() 的作用域(仅限 public/ 目录)与 storage:link 的映射逻辑(public/storage/ → storage/app/public/)。只需两步即可解决:
① 工厂中用 faker->image('users', ...) 保存相对路径;
② Blade 中用 Storage::url($user->image) 生成 URL。
从此告别 404,让头像稳稳加载。