CORSなJSだけでS3へのMultipartUL&DLする場合の必要な設定

More than 3 years have passed since last update.


S3に対しCORSでJavascriptだけでマルチパートアップロードやダウンロードする場合の必要な設定

色々なサイトで値をアスタリスクで済ませてあるパターンが多くて、なんかモヤっとしたので、必要最小限は何か試してみた結果をここにすまし汁


このTopicの前提条件


  • IAMアカウントのキーでアクセスする

  • ブラウザのから直接S3に対しアップロードやダウンロードを行う(javacriptのみ)

  • アップロードはマルチパートアップロードを使用する


S3のCORS設定

必要になる定義を以下に記載します


AllowOrigin

クロスオリジンなので全てを許可せざるを得ないので値は*

<AllowedOrigin>*</AllowedOrigin>


MaxAgeSeconds

お好みで、値は秒数。見本では2時間相当。

<MaxAgeSeconds>7200</MaxAgeSeconds>


ExposeHeader

晒すレスポンスヘッダー、マルチパートアップロード等でブラウザとS3がやりとりするのに必要な値をレスポンスしてあげる必要がある。ETagとか。

<ExposeHeader>ETag</ExposeHeader>

<ExposeHeader>x-amz-request-id</ExposeHeader>

<ExposeHeader>x-amz-id-2</ExposeHeader>


AllowedHeader

許可するヘッダーのように思えるが、実際には必要なヘッダーの定義。だと思う。

ここに必要なヘッダーが定義されていないとS3とのやりとりが失敗する。

<AllowedHeader>Authorization</AllowedHeader>

<AllowedHeader>Content-Type</AllowedHeader>

<AllowedHeader>User-Agent</AllowedHeader>

<AllowedHeader>x-amz-date</AllowedHeader>

<AllowedHeader>x-amz-user-agent</AllowedHeader>

<AllowedHeader>x-amz-storage-class</AllowedHeader>

<AllowedHeader>x-amz-acl</AllowedHeader>

User-Agentも必要でx-amz-user-agentも必要とか意味不明。

→値を見たら全く違う内容でした。つまりどちらも違う役割。

 x-amz-user-agentは「aws-sdk-js/2.0.0-rc13」みたいなSDKの種類やバージョンの値のようです。


必要ヘッダーの検証方法

AllowedHeaderの定義をアスタリスクにした状態でアップロード時のリクエストヘッダーをChromeの開発者ツールで観察し、そこに登場したヘッダー+「x-amz-storage-class」+「x-amz-acl」だけをAllowedHeaderとして編集してそこから一つづつ定義から消しながらマルチパートアップロードをトライアンドエラー。

結果、上記のヘッダー群が残りました。アカウント設定やらACLやらプログラムコードの書き方によっては違いが出てくるかもしれません。


最終結果のヘッダーまとめ

以下がS3へのJavascriptから直接ダウンロード&アップロード(マルチパート)する場合のS3のコントロールパネルから行うCORS設定XMLです。

<?xml version="1.0" encoding="UTF-8"?>

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>7200</MaxAgeSeconds>
<ExposeHeader>ETag</ExposeHeader>
<ExposeHeader>x-amz-request-id</ExposeHeader>
<ExposeHeader>x-amz-id-2</ExposeHeader>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>User-Agent</AllowedHeader>
<AllowedHeader>X-Amz-Date</AllowedHeader>
<AllowedHeader>X-Amz-User-Agent</AllowedHeader>
<AllowedHeader>x-amz-storage-class</AllowedHeader>
<AllowedHeader>x-amz-acl</AllowedHeader>
</CORSRule>
</CORSConfiguration>


javascript側のおおまかな流れ(マルチパートアップロード編)

詳しくはAWSのjavascript用SDKのドキュメントというかリファレンス見てください。

今回はアカウント情報とかノーガードな流れなので実装する際に気をつけてくだしあ


  • フォームでファイルを選択させる

  • 送信イベント発火(このタイミングで一旦ファイル情報だけPHPかなんかに送信してシグネチャーの生成とファイルのチェックとかすると良いのでしょう)

  • ファイル情報を取得

  • AWS.config.updateしたりS3インスタンス生成したり

  • s3インスタンスのcreateMultipartUploadメソッド実行してマルチパート処理スタート。戻り値に重要なUploadIdがあるよ!

  • ファイルをBlobとして分割送信サイズづつにsliceしながらループ処理でs3インスタンスのuploadPartメソッドを実行

  • 戻り値にETagとかあるから値を配列に格納

  • 全てのパーツの送信が終わったらs3インスタンスのcompleteMultipartUploadメソッドを実行※この時、引数のオブジェクトの中身にuploadPartメソッドの戻り値の塊が必要なのです。

  • どこかでエラーが起きたらs3インスタンスのabortMultipartUploadを読んで中止しましょう。

12GBのファイルをマルチパートアップロードしてみたら、途中大量にエラー出たけど最終的にアップロード出来てました。だいたい1時間半位かかりました。

※2500分割位で送信して5000件以上エラー出てた。


追記

2015/12/10現在では自分は以下の様な設定で使っています。

<?xml version="1.0" encoding="UTF-8"?>

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>7200</MaxAgeSeconds>
<ExposeHeader>ETag</ExposeHeader>
<ExposeHeader>x-amz-request-id</ExposeHeader>
<ExposeHeader>x-amz-id-2</ExposeHeader>
<ExposeHeader>x-amz-meta-custom-header</ExposeHeader>
<AllowedHeader>Origin</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>User-Agent</AllowedHeader>
<AllowedHeader>X-Amz-Date</AllowedHeader>
<AllowedHeader>X-Amz-User-Agent</AllowedHeader>
<AllowedHeader>x-amz-storage-class</AllowedHeader>
<AllowedHeader>x-amz-acl</AllowedHeader>
<AllowedHeader>x-amz-security-token</AllowedHeader>
</CORSRule>
</CORSConfiguration>

いつの間にかExposeHeaderにx-amz-meta-custom-headerと

AllowedHeaderにx-amz-security-tokenを追加してました。

Cognito使うようになったからかな。。。

また、AllowedHeaderにOriginを追加しているのはこうしないとSafariの場合に

403エラーがでるので追加しています。仕組みは分かっていません。