laravel 中应使用 medialibrary 同步生成并缓存缩略图:安装后在模型中注册 nonqueued() 转换,上传时自动保存至磁盘;通过路由或中间件直接返回文件,配置磁盘与集合确保复用,生产环境启用转换。

在 Laravel 项目中集成文件管理器时,用户上传图片后需即时生成缩略图供预览,但每次访问都实时处理会导致 CPU 持续飙升、响应延迟超过 1.2 秒,页面卡顿明显。必须让缩略图在首次访问时生成并持久缓存,后续请求直接返回磁盘文件。
使用 Laravel MediaLibrary 自动生成缩略图
MediaLibrary 是 Laravel 生态中最成熟的媒体管理方案,它原生支持按需定义转换规则,并自动触发缩略图生成与存储。
第一步:执行安装命令并发布迁移和配置:
composer require spatie/laravel-medialibrary && php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations" && php artisan migrate
第二步:在模型中添加 HasMedia trait 并注册转换器:
在 App\Models\File 或对应媒体宿主模型中,加入 use Spatie\MediaLibrary\HasMedia; 和 implements HasMedia 接口;再在 boot() 中调用 $this->addMediaConversion('thumb')->width(300)->height(200)->nonQueued();
第三步:上传文件时触发转换:
$media = $model->addMedia($request->file('image'))->toMediaCollection(); 这行代码执行后,MediaLibrary 会立即生成 thumb 转换并保存到 storage/app/media/xxx/thumb.jpg,无需额外调用 convert()。
注意:nonQueued() 是关键,它强制同步生成,避免队列延迟导致预览空白;若用 queued(),则必须确保队列服务正在运行且无积压。
为缩略图 URL 添加缓存中间件拦截
当浏览器请求 /storage/media/123/thumb.jpg 时,Laravel 默认走完整 HTTP 生命周期,开销大。应绕过路由和控制器,由中间件直接读取磁盘并返回响应。
方法一:自定义中间件直接响应静态文件
创建 app/Http/Middleware/ThumbnailCache.php,handle 方法内判断请求路径是否匹配 ^/storage/media/\d+/thumb\.jpg$,匹配则用 response()->file() 返回物理路径,状态码 200,Content-Type 自动推断。
方法二:在 routes/web.php 顶部添加高优先级路由
Route::get('/storage/media/{id}/thumb.jpg', function ($id) { $path = storage_path("app/media/{$id}/thumb.jpg"); return response()->file($path, ['Cache-Control' => 'public, max-age=31536000']); })->whereNumber('id');
【该路由必须放在所有其他路由之前,否则会被 RouteServiceProvider 的 fallback 拦截】
启用文件系统级缓存策略
缩略图一旦生成,就应长期驻留磁盘,同时防止重复生成消耗资源。MediaLibrary 默认不覆盖已有转换,但需主动控制缓存行为。
① 在 config/media-library.php 中设置 'should_preserve_original' => false,避免冗余保留原图副本;
② 将 'disk_name' 设为 'local' 或专用磁盘(如 'thumbnails'),并在 filesystems.php 中为其配置独立 root 路径,例如 'root' => storage_path('app/thumbnails');
③ 关键操作:在 addMediaConversion 链中追加 performOnCollections('images'),并确保上传时指定 $model->addMedia(...)->toMediaCollection('images'),这样 MediaLibrary 才能精准识别并复用已生成的缩略图,不会为同一文件反复创建新 media 记录。
④ 禁用开发环境下的自动转换:在 APP_ENV=local 时,MediaLibrary 默认跳过转换以加速调试;上线前务必确认 .env 中 APP_ENV=production,否则缩略图永不生成。











