Laravel中需通过配置验证文件真实路径、数据库记录delete_at字段并编写定时命令清理过期文件,避免误删和磁盘垃圾。

在 Laravel 应用中,用户上传的图片、PDF 等临时文件若未与数据库记录联动清理,24 小时后就会变成磁盘垃圾——既无法访问又持续占用空间,甚至因路径误判导致 unlink() 失败却无报错。
确认文件真实存储位置,避免误删失败
第一步:打开 config/filesystems.php,检查 public 磁盘配置是否为 'root' => storage_path('app/public');【这是真实物理路径,不是 public/storage】
第二步:执行 php artisan tinker,输入 Storage::disk('public')->path('/media/test.jpg') → 返回类似 "/var/www/app/storage/app/public/media/test.jpg";这才是文件实际所在位置。
第三步:如果曾用 unlink(public_path('storage').$path) 删除过文件,立刻停止——该路径指向符号链接目标(public/storage),但文件根本不在那里,操作永远返回 false。
数据库记录带过期时间写入
方法一:使用 Carbon 设置精确删除时间
在控制器中保存上传文件时,必须同时写入 delete_at 字段:delete_at => Carbon::now()->addHours(24);【字段类型必须是 DATETIME,不能是 DATE】,否则跨零点时可能漏删。
方法二:避免用 timestamp 或 int 类型存 Unix 时间戳——Laravel 的 whereDate() 和 whereTime() 查询无法高效命中索引,会导致全表扫描。
编写自动清理命令
运行 php artisan make:command CleanupExpiredMedia 创建命令类。
在 handle() 方法中写入核心逻辑:
① 查询所有 delete_at 已过期的记录:$expired = ReceivedMedia::where('delete_at', 'get();
② 遍历并用 Storage::disk('public')->delete($item->media) 删除文件;这一步会真正作用于 storage/app/public/ 目录,安全可靠。
③ 删除成功后,调用 $item->delete() 清除数据库记录;注意不要颠倒顺序——先删库再删文件,可能导致文件残留。
配置定时任务执行清理
打开 app/Console/Kernel.php,在 schedule() 方法中添加:
$schedule->command('cleanup:expired-media')->hourly();
确保服务器 Cron 已启用:* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
该命令每小时执行一次,只处理已过期且尚未清理的记录,不重复触发、不阻塞主线程。


















