使用预先签名的URL将本机上传到S3

Col*_*ole 12 xmlhttprequest amazon-s3 amazon-web-services pre-signed-url react-native

尝试使用预先签名的URL从React Native上传图像到没有运气.这是我的代码:

在节点中生成预先签名的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);
Run Code Online (Sandbox Code Playgroud)

这是对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);
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

我可以使用生成的url成功卷曲并映像到S3,我似乎能够成功地从RN发送到requestb.in(但是我只能在requestb.in上看到原始数据,所以不能100%确定图像是否正确那里).

基于这一切,我已经将我的问题缩小到1)我的图像没有正确上传期间,或者2)不知何故S3想要我的请求的方式与它的进入方式不同.

任何帮助将是muuuuuuucchhhh赞赏!

UPDATE

如果body只是文本({'data':'foo'}),可以成功地从RN发布到S3.也许AWS不喜欢多种数据?我如何只在RN中发送文件???

Edw*_*uel 13

FormData将创建一个multipart/form-data请求.S3 PUT对象需要其请求主体为文件.

您只需要在请求正文中发送文件而不将其包装到FormData:

function uploadFile(file, signedRequest, url) {
  const xhr = new XMLHttpRequest();
  xhr.open('PUT', signedRequest);
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if(xhr.status === 200) {
        alert(url);
      } else {
        alert('Could not upload file.');
      }
    }
  };
  xhr.send(file);
};
Run Code Online (Sandbox Code Playgroud)

例如,在浏览器中查看https://devcenter.heroku.com/articles/s3-upload-node.另请确保您的Content-Type标头与签名的网址请求相匹配.

  • 您能否详细说明确保Content-Type标头与签名的URL请求相匹配?我不太明白你的意思. (2认同)

小智 6

"rn-fetch-blob": 0.12.0,
"react-native": 0.61.5
Run Code Online (Sandbox Code Playgroud)

此代码适用于 Android 和 iOS

const response = await RNFetchBlob.fetch(
  'PUT',
  presignedUrl,
  {
    'Content-Type': undefined
  },
  RNFetchBlob.wrap(file.path.replace('file://', '')),
)
Run Code Online (Sandbox Code Playgroud)

{'Content-Type': undefined}iOS 需要备注


Pet*_*ski 5

我在iOS和Android上上传到预先签名的S3 URL上浪费了太多时间。对我有用的rn-fetch-blob lib

程式码片段:

import RNFetchBlob from 'rn-fetch-blob'

const preSignedURL = 'pre-signed url'
const pathToImage = '/path/to/image.jpg' // without file:// scheme at the beginning
const headers = {}

RNFetchBlob.fetch('PUT', preSignedURL, headers, RNFetchBlob.wrap(pathToImage))
Run Code Online (Sandbox Code Playgroud)

  • 你是我的救星! (3认同)