如何修复使用Axios通过S3预签名URL上传文件时的InvalidArgument 400错误
问题根因分析
这个400 InvalidArgument错误的核心触发原因是请求S3预签名URL时同时存在两种鉴权信息:
- 你获取到的S3预签名URL本身已经在查询参数中携带了
X-Amz-Algorithm、Signature等完整鉴权参数,本身已经具备访问S3的权限 - 你的Axios全局配置/请求拦截器默认会给所有请求携带
Authorization: Bearer xxx身份头,请求S3的时候也被带上了,S3不允许同时存在两种鉴权方式,因此抛出错误
另外还有一个隐含问题:S3的PUT预签名URL需要直接上传文件二进制内容,你当前用FormData包裹文件会导致内容格式不匹配,上传后文件无法正常打开,也可能触发额外的签名校验错误。
解决方案
方案1:请求S3时手动清空鉴权头,直接传递文件
修改上传部分的代码即可,示例如下:
// get the pre-signed URL this.$axios.get(this.ApiGatewayUrl, { headers: { Authorization: this.$auth.strategy.token.get() } }).then((response) => { // 直接传文件对象,同时清空Authorization头避免鉴权冲突 this.$axios.put(response.data, this.myFile, { headers: { Authorization: '' } }).then((response) => { this.setState({ statusCode: response.status, }) }) })
方案2:Axios拦截器全局适配
如果你是通过Axios全局拦截器统一添加的Authorization头,可以在拦截器中增加域名判断逻辑,只要是S3相关的请求就不添加该头,避免后续出现同类问题:
// axios请求拦截器示例 axios.interceptors.request.use(config => { // 仅请求自有业务接口时携带鉴权头,S3请求跳过 if (!config.url.includes('amazonaws.com') || config.url.includes('execute-api')) { config.headers.Authorization = this.$auth.strategy.token.get() } return config })
方案3:临时替代方案
可以直接用原生fetch发送PUT请求,不会继承Axios的全局头配置:
fetch(response.data, { method: 'PUT', body: this.myFile })
你当前的S3存储桶CORS配置符合要求,无需额外修改。
内容的提问来源于stack exchange,提问作者Sébastien Serre
相关产品推荐
相关产品推荐

