Help us understand the problem. What is going on with this article?

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エラーがでるので追加しています。仕組みは分かっていません。

sakadonohito
FileMaker,PHP,JavaScript
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした