Blog

ブログ

2015.06.18

サーバーレスでJavaScript だけで画像ファイルをアップロードする方法

こんにちは、本間です。

今日は AWS JavaScript SDK を利用した内容です。

普通、ファイルをアップロードするにはどこかファイルを置くためのサーバーが必要ですが、Amazon S3 を使えば自前のサーバーを介さずに生のHTMLのみで直接ファイルをアップロードすることができます!

S3に直接ファイルを上げることで、サーバーの負荷を軽減することもできますし、何よりアップロード速度が早くなるのでユーザーエクスペリエンスも向上することと思います。

ちょっとした前準備が必要ですが、実装自体は極めて簡単です。それでは始めてみましょう。

Amazon Cognito で Identity Pool の作成

Amazon Cognito を利用し、アクセスの制限されたトークンを発行します。Amazon Cognito にて、Identity Pool を作成します。

identity pool

name は適当に、unauthenticated identities にチェックを入れます。 unauthenticated identities とは、facebookやgoogleなどの認証を通さずにAWSへアクセスできるようにするための非認証ユーザーを許可するかの選択です。

続いて新規ロールを作成します。これはそのまま許可を選択します。ここで新規IAMロールを作成します。このIAMロールに対してアクセス権限を与えます。

これで出来上がった後に表示される、Cognito Identity Pool IDをメモっておいてください。JavaScriptコーディング時に利用します。

IAM ロールの設定

続いて Amazon S3 にファイルをアップロードできるようにさせるためにIAMロールを設定します。

ヘッダーの名前タブ - 認証情報 - ロール へ移ります。ここに、先ほど作成したCognito の IAMロールがありますので、これのうち、**UnauthRoleを選択します。

ここでロールポリシーの作成を選択し、PolicyGenerator を選択。以下のようにセットします。

  • 許可にチェック
  • AWS サービスに Amazon S3を選択
  • アクションに s3:PutObject, s3:PutObjectAcl
  • リソースネームに arn:aws:s3:::S3バケット名/* (Amazon S3にてバケットを作成しておいてください)

policyGenerator

S3 のバケット設定

S3側でCORS(Cross-Origin Resource Sharing)の設定をします。この設定をするからこそ、JavaScriptで外部のサーバーにAjaxを投げらるようになり、サーバーレスのアップロードができるようになります!

Amazon S3のバケットのプロパティにて、 アクセス許可にあるCORS 設定の編集 を選択します。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
        <AllowedHeader>Content-*</AllowedHeader>
        <AllowedHeader>Host</AllowedHeader>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

これにて、 AWSコンソール側の設定は完了です。

JavaScriptコーディング

こちらはあっという間にできます。


<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="//sdk.amazonaws.com/js/aws-sdk-2.1.34.min.js"></script>


<input type="file" name="upload" id="upload-file">
<a href="javascript:void(0)" id="apply-upload">アップロード</a>

<script>
$(function() {
  var s3_client = function() {
    AWS.config.region = "us-east-1";
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({IdentityPoolId: "Cognitoで取得したIdentity Pool Id"});
    AWS.config.credentials.get(function(err) {
        if (!err) {
            console.log("Cognito Identify Id: " + AWS.config.credentials.identityId);
        }
    });
    return new AWS.S3({params: {Bucket: "バケット名"}});
  };

  $("#apply-upload").click(function() {
    var file = $("#upload-file").prop("files")[0];
    var timestamp = new Date().getTime();
    var filename = "file" + timestamp + ".jpg";
    s3_client().putObject({Key: filename, ContentType: file.type, Body: file, ACL: "public-read"},
    function(err, data){
      // if failed, alert
      if(data !== null){
        alert("アップロード成功!");
      } else {
        alert("アップロード失敗.");
      }
    });
  });
)};
</script>

こんな感じでやれば、ファイル選択してアップロードをクリックするとAmazon S3に画像がアップロードされていることでしょう。

まとめ

いかがでしたでしょうか。 ぜひお試しください。