【发布时间】:2016-10-12 03:16:58
【问题描述】:
一直在尝试使用预签名的 url 从 React Native 将图像上传到 S3,但没有成功。这是我的代码:
在节点中生成预签名的url:
const s3 = new aws.S3();
const s3Params = {
Bucket: bucket,
Key: fileName,
Expires: 60,
ContentType: 'image/jpeg',
ACL: 'public-read'
};
return s3.getSignedUrl('putObject', s3Params);
这是对 S3 的 RN 请求:
var file = {
uri: game.pictureToSubmitUri,
type: 'image/jpeg',
name: 'image.jpg',
};
const xhr = new XMLHttpRequest();
var body = new FormData();
body.append('file', file);
xhr.open('PUT', signedRequest);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
alert('Posted!');
}
else{
alert('Could not upload file.');
}
}
};
xhr.send(body);
game.pictureToSubmitUri = assets-library://asset/asset.JPG?id=A282A2C5-31C8-489F-9652-7D3BD5A1FAA4&ext=JPG
signedRequest = https://my-bucket.s3-us-west-1.amazonaws.com/8bd2d4b9-3206-4bff-944d-e06f872d8be3?AWSAccessKeyId=AKIAIOLHQY4GAXN26FOQ&Content-Type=image%2Fjpeg&Expires=1465671117&Signature=bkQIp5lgzuYrt2vyl7rqpCXPcps%3D&x-amz-acl=public-read
错误信息:
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>
我可以使用生成的 url 成功地 curl 和图像到 S3,并且我似乎能够从 RN 成功发布到 requestb.in(但是我只能看到 requestb.in 上的原始数据,所以不能 100% 确定图像正确存在)。
基于这一切,我已将问题缩小到 1) 我的图像上传时间不正确,或 2) S3 希望我的请求的方式与它的传入方式不同。
任何帮助将不胜感激!
更新
如果正文只是文本({'data': 'foo'}),可以成功地从 RN 发布到 S3。也许 AWS 不喜欢多种形式的数据?如何在 RN 中仅作为文件发送???
【问题讨论】:
-
不确定您的签名为何无效。我有几乎相同的签名代码,它工作正常。您的空成功上传是由于您将路径作为 URI 传递。
file:///var/.../4BBAE22E-DADC-4240-A266-8E469C0636B8.jpg应该可以工作。 -
您的 AWS 密钥是否有任何尾随转发“/”?
-
@DanielBasedow 我不认为签名无效。我可以使用它 curl 上传图片。我认为我的 RN 请求的形成方式有问题?
-
@Cole 只是想知道这是否是最佳实践?当客户端上的用户想要上传图片时,我应该将文件名发送到 Node.js 服务器以生成预签名 URL -> 将预签名 URL 发送回客户端应用程序 -> 然后客户端应用程序上传到预签名 URL?
-
@kayla 我的理解是从客户端直接上传到 S3 是首选方法是的。通过后端发送文件会给服务器带来不必要的负载。以下是 heroku 文档:devcenter.heroku.com/articles/s3-upload-node
标签: amazon-web-services amazon-s3 xmlhttprequest react-native pre-signed-url