使用CloudFront时无法删除AWS S3存储桶文件的问题排查
Laravel+Filament+Spatie MediaLibrary 结合CloudFront后无法删除S3文件问题
环境配置
- Laravel 10
- Filament 3
- Spatie MediaLibrary(最新版)
- AWS S3 + CloudFront 内容分发
S3存储桶策略
{"Version": "2012-10-17","Id": "PolicyForCloudFrontPrivateContent","Statement": [{"Sid": "AllowCloudFrontServicePrincipal","Effect": "Allow","Principal": {"Service": "cloudfront.amazonaws.com"},"Action": ["s3:GetObject","s3:DeleteObject"],"Resource": "arn:aws:s3:::xxxxxx.xxx/*","Condition": {"StringEquals": {"AWS:SourceArn": "arn:aws:cloudfront::xxxxx:distribution/xxxxxx"}}}]
Laravel 文件系统配置(config/filesystems.php)
'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), 'throw' => false, ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL') . '/storage', 'visibility' => 'public', 'throw' => false, ], 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'folder' => env('AWS_FOLDER'), 'view_url' => env('AWS_VIEW_URL'), 'url' => env('AWS_S3_CLOUDFRONT'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => true, ], ]
问题描述
未使用CloudFront前,通过SpatieMediaLibraryFileUpload组件更新/删除文件时,文件会正常从S3存储桶中移除;切换到CloudFront分发后,仅能创建文件,无法删除或替换文件。
- 已确认不是缓存问题:通过AWS控制台以root身份直接查看存储桶,文件确实未被删除
- Laravel日志无错误记录
- 数据库中的媒体记录已被删除/更新,但S3存储桶内的文件仍保留
已排查操作:
- 将存储桶策略中的
Principal设置为"*",问题依旧存在
期望行为:使用SpatieMediaLibraryFileUpload组件更新/删除文件时,文件应同步从S3存储桶中移除或更新。
问题排查与解决方案
1. 补全IAM用户的S3操作权限
你的存储桶策略仅允许CloudFront服务主体执行删除操作,但Laravel应用是通过IAM密钥(AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY)直接访问S3的,当前使用的IAM用户/角色需要拥有明确的删除、写入权限:
给该IAM用户添加如下权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::xxxxxx.xxx/*" } ] }
注:存储桶策略和IAM用户权限是叠加生效的,两者都需要允许对应操作才能执行成功。
2. 确认CloudFront配置不影响S3写入/删除
CloudFront仅负责内容分发,不会直接拦截S3的API操作:
- 你在
filesystems.php中设置的url为CloudFront域名,仅影响文件的前端访问地址,Laravel对S3的删除/更新操作是直接调用S3 API,不走CloudFront - 检查CloudFront的Origin Access Control(OAC)或Origin Access Identity(OAI)配置,确保仅限制读取权限,未干扰写入/删除操作
3. 验证Spatie MediaLibrary的磁盘绑定
确认你的媒体模型正确指定了使用s3磁盘:
use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; class YourModel extends Model implements HasMedia { use InteractsWithMedia; public function registerMediaCollections(): void { $this->addMediaCollection('your-collection') ->useDisk('s3'); // 必须明确指定使用s3磁盘 } }
同时确认删除操作触发了MediaLibrary的原生逻辑,比如调用$model->clearMediaCollection()或$mediaItem->delete()。
4. 开启AWS SDK调试日志排查细节
在.env中添加以下配置,开启详细的AWS请求日志:
AWS_DEBUG=true LOG_CHANNEL=stack LOG_LEVEL=debug
执行删除操作后,查看storage/logs/laravel.log中的AWS SDK请求记录,可直接定位是否存在API调用失败的具体原因。
内容的提问来源于stack exchange,提问作者Zeli Torres
相关产品推荐
相关产品推荐

