媒体同步到S3后后台能看到缩略图,前台原图却403。先分清前台URL是公开对象、CloudFront私有分发还是应用签名URL;Bucket私有时仅把文件上传成功还不够。
排查记录
我保留了一个失败样本,并用同样输入在无缓存或单节点条件下再跑一遍。这样可以把前端假象、缓存和真正的数据问题分开。
我先看了这几处
- 复制前台最终图片URL看响应头中的Server和x-cache,确认403来自S3还是CDN。
- 检查对象key大小写、Content-Type及CloudFront origin access配置。
curl -I "https://media.example.com/catalog/product/a/b/example.jpg" aws s3api head-object --bucket shop-media --key catalog/product/a/b/example.jpg bin/magento remote-storage:sync bin/magento config:show system/media_storage_configuration/media_database
日志取样要带上请求时间、Store View、实体ID和部署版本。只截一行异常往往不够,至少保留错误前后几十行,才能判断是入口参数还是后续状态被改写。
处理办法
推荐保持Bucket私有,通过CloudFront OAC/OAI授予读取,并让Magento base media URL指向分发域名。Bucket Policy只授权该分发,不要开放Principal:*。若使用签名URL,确认缓存TTL短于签名有效期且查询参数未被代理删除。同步后做一次指定对象head检查。
修改范围
- 先在单个SKU、单个订单或单个Store验证。
- 保留可回退的旧配置,不覆盖原始证据。
- 需要批量处理时分批提交并输出成功/失败清单。
回归时别只刷新页面
- 匿名访问CDN URL为200
- 直接S3私有URL仍被拒绝
- 新上传与历史图片都可读
- 缓存失效后不会间歇403
验收不只看后台提示“成功”。我还会从前台/API再走一次真实链路,并在下一轮cron、索引或缓存命中后重复检查,确认不是短暂正常。
补记
为省事打开整个Bucket公读会暴露未发布媒体和其他对象。

