React Native - S3 Pre-signed URL 上传问题。 cURL 有效,fetch 无效 - 403 SignatureDoesNotMatch
React Native - S3 Pre-signed URL upload issues. cURL works, fetch doesn't - 403 SignatureDoesNotMatch
如标题所示,我可以毫无问题地从 lambda 获得 pre-signed URL。 URL 在 cURL 中工作,可以毫无问题地上传图像,并且还可以与测试 python 脚本一起工作。
我一辈子都弄不明白为什么这在 javascript 中不起作用(特别是 React Native,在 Expo 中)。
这里大致是感兴趣的代码:
const getBlob = async (fileUri) => {
const resp = await fetch(fileUri);
const imageBody = await resp.blob();
return imageBody;
};
async function putPhoto(photoURI){
// code to get the S3URL
const imageBlob = await getBlob(photoURI)
response = await fetch(S3URL,{
method: "PUT",
body: imageBlob,
// headers: {
// "Content-Type": "application/json"
// }
})
特别令人抓狂,因为来自 S3 的响应包含 URL,我可以显式地 cURL 并成功解析:
curl -X PUT -T .\test.jpg "https://<bucketname>.s3.amazonaws.com/<lambda generated hash>.jpg?AWSAccessKeyId=<>&x-amz-security-token=<>&Expires=<>"
当然 'sensitive data' 在 <> 中被替换。
我唯一能看到其他人有共同问题的是 headers - 我也尝试输入:
headers: {}
我假设这会覆盖 headers 的任何全局范围,我忘记了。
有什么建议吗?非常感谢。
好的,看起来 S3 在获取 fetch() 请求时非常具体地需要正确的 header,而不关心来自 cURL 的那些相同的 header。或者至少,在这种情况下需要这样设置才能获取。
Python lambda 代码:
url = boto3.client('s3').generate_presigned_url(
ClientMethod='put_object',
Params={'Bucket': BUCKET_NAME, 'Key': full_id, 'ContentType': 'application/octet-stream'},
ExpiresIn=3600
)
关键是添加 Content-Type 参数,如图所示。
此外,将我上面的代码更改为(参见 Content-Type):
async function putPhoto(photoURI){
// code to get the S3URL
const imageBlob = await getBlob(photoURI)
response = await fetch(S3URL,{
method: "PUT",
body: imageBlob,
headers: {
"Content-Type": "application/octet-stream"
}
})
如标题所示,我可以毫无问题地从 lambda 获得 pre-signed URL。 URL 在 cURL 中工作,可以毫无问题地上传图像,并且还可以与测试 python 脚本一起工作。
我一辈子都弄不明白为什么这在 javascript 中不起作用(特别是 React Native,在 Expo 中)。
这里大致是感兴趣的代码:
const getBlob = async (fileUri) => {
const resp = await fetch(fileUri);
const imageBody = await resp.blob();
return imageBody;
};
async function putPhoto(photoURI){
// code to get the S3URL
const imageBlob = await getBlob(photoURI)
response = await fetch(S3URL,{
method: "PUT",
body: imageBlob,
// headers: {
// "Content-Type": "application/json"
// }
})
特别令人抓狂,因为来自 S3 的响应包含 URL,我可以显式地 cURL 并成功解析:
curl -X PUT -T .\test.jpg "https://<bucketname>.s3.amazonaws.com/<lambda generated hash>.jpg?AWSAccessKeyId=<>&x-amz-security-token=<>&Expires=<>"
当然 'sensitive data' 在 <> 中被替换。
我唯一能看到其他人有共同问题的是 headers - 我也尝试输入:
headers: {}
我假设这会覆盖 headers 的任何全局范围,我忘记了。
有什么建议吗?非常感谢。
好的,看起来 S3 在获取 fetch() 请求时非常具体地需要正确的 header,而不关心来自 cURL 的那些相同的 header。或者至少,在这种情况下需要这样设置才能获取。
Python lambda 代码:
url = boto3.client('s3').generate_presigned_url(
ClientMethod='put_object',
Params={'Bucket': BUCKET_NAME, 'Key': full_id, 'ContentType': 'application/octet-stream'},
ExpiresIn=3600
)
关键是添加 Content-Type 参数,如图所示。
此外,将我上面的代码更改为(参见 Content-Type):
async function putPhoto(photoURI){
// code to get the S3URL
const imageBlob = await getBlob(photoURI)
response = await fetch(S3URL,{
method: "PUT",
body: imageBlob,
headers: {
"Content-Type": "application/octet-stream"
}
})