直传成功后前端拿 response.headers.get('ETag') 一直是 null,Network 面板里响应头明明有 ETag。换成本地开发环境又能取到。日志里能对上时间点,这种反而好排。
跨域请求默认只暴露六个安全响应头,ETag 不在其中。服务端要在 ExposeHeaders 里显式列出,浏览器才允许 JS 读。预检通过不代表响应头可读,这是两件事。这一点先确认清楚,后面就不用反复试。
aws s3api put-bucket-cors --bucket b --cors-configuration \
{"CORSRules":[{"AllowedOrigins":["https://a.com"],"AllowedMethods":["PUT","GET"],"AllowedHeaders":["*"],"ExposeHeaders":["ETag"],"MaxAgeSeconds":600}]}
「CORS ExposeHeaders」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
别只看报错的最后一行,往上看几行,真正的起因通常在上面。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。
处理上按这个顺序:桶的 CORS 规则里补 ExposeHeaders 包含 ETag;AllowedHeader 里放行前端实际发送的头;确认预检命中的是这条规则 不是兜底规则;改完用无痕窗口重试 避免旧预检结果缓存。
结果对不对很好判断,前端能读到 ETag 且值以引号包裹,直传后的校验流程可以继续。
