web-dev-qa-db-ja.com

React事前に署名されたURLを使用したS3へのネイティブアップロード

React Native using pre-signedurl。から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を使用してS3に正常にカールして画像を作成でき、RNからrequestb.inに正常に投稿できるようです(ただし、requestb.inの生データしか表示できないため、画像が適切であるかどうかを100%確認することはできません。そこ)。

これらすべてに基づいて、問題を1)画像が正しくアップロードされていない期間、または2)S3がリクエストを要求する方法が受信方法と異なることに絞り込みました。

どんな助けでもmuuuuuucchhhhに感謝します!

更新

本文が単なるテキスト({'data': 'foo'})の場合、RNからS3に正常に投稿できます。おそらくAWSはマルチフォームデータが好きではありませんか? RNでファイルとして送信するにはどうすればよいですか?

13
Cole

FormDatamultipart/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);
};

たとえば、ブラウザで https://devcenter.heroku.com/articles/s3-upload-node を参照してください。また、Content-Typeヘッダーが署名付きURLリクエストと一致していることを確認してください。

13
Edward Samuel

IOSとAndroidの両方で事前に署名されたS3URLにアップロードするのに多くの時間を無駄にしました。私のために働いたのは 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))
4
Peter Machowski