LoginSignup
24
33

More than 5 years have passed since last update.

AWS+Reactアプリ作成入門(S3編)

Last updated at Posted at 2017-11-07

AWS+Reactアプリ作成入門(Cognito編)
AWS+Reactアプリ作成入門(S3編)
AWS+Reactアプリ作成入門(DynamoDB編)
AWS+Reactアプリ作成入門(IAM Role編)
AWS+Reactアプリ作成入門(ログイン後のAdmin編)

今回作成したアプリ ==>久喜SNS

 前回はユーザ認証(Cognito)周りを中心に述べましたが、今回はS3の利用について述べたいと思います。S3は2つの目的で使います。画像の保存とReactアプリの保存です。Reactアプリの開発時は別サーバで行い、完成したらS3にdeployします。

 まずAWSコンソールでS3にバケットを作成します。Reactアプリを走らせますので静的ホスティングをONにします。プログラムをdeployした時に誰でもアクセスできるように、以下のようにバケットポリシーを設定します。これで誰でもRead Onlyでプログラムにアクセスでき、ホスティングのページに示されたURLにアクセスするとプログラムが起動されます。Cognitoでプログラムの実行に権限を与えることはできますが、バケットポリシーはプログラムの実行以前の、プログラムのロードに必要となります。プログラムから画像をアップロードしたり削除したりするCognitoの権限(Role)については別の機会にしまします。

バケットポリシー
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AddPerm",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::examplebucket/*"]
    }
  ]
}

公式サイト:Granting Read-Only Permission to an Anonymous User

 Cognitoは面倒でしたが、S3はシンプルです。信頼性が高く低価格なので、認証が不要であれば、簡単にReactアプリを作成し、以下のコマンド一発でdeployすることが可能です。react-create-appで作成したプロジェクトのディレクトリーで実行します。この辺がMeteorにない魅力ですね。

npm run build && aws s3 sync build/ s3://バケット名

 このコマンドを使うためには予めaws-cliを設定しておく必要があります。ついでですのでその手順を載せておきます。

1.AWS-CLIのインストール

 公式サイト「AWS CLI のインストールと設定」に従って行います。
http://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html

(1)インストール
 次のコマンドでインストールできます。

curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py
sudo pip install awscli
aws help

(2)設定
 まずAWSコンソールのIAM画面のユーザで自分を検索し、アクセスキーとシークレットキーの入手します。認証情報タブでアクセスキーの作成をクリックするとポップアップにシークレッドキーが表示されますので、忘れずにコピーしておいてください。

aws configure
AWS Access Key ID [None]: AKIAXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

(3)確認
 念のため確認しておきます。これでaws-cliが使えるようになりました。

$ cat ~/.aws/credentials
[default]
aws_access_key_id = AKIAXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXX

$ cat ~/.aws/config
[default]
output = json
region = ap-northeast-1

2.画像のアップロード

 ReactアプリからS3にアクセスするためには権限が必要となります。権限は非ログインユーザとログインユーザにそれぞれ付与されます。そのためにはCognitoの設定が必要となりますが、これについては前回述べましたので参照してください。

 まずファイル選択ですが以下のJSXで行います

ファイル選択ボタン
<input type="file" onChange={this.handleFileChange.bind(this)}/>

 this.state.fileに選択したファイルを保存します。e.target.files[0]で選択したファイルにアクセスできます。

ファイル選択ハンドラー
  handleFileChange(e) {
    this.setState({file: e.target.files[0]});
  }

 送信ボタンを押された時のハンドラーの一部です。通常callbackの中で処理を行いますので、予め _self=this としていると仮定してください。s3.putObject()で画像ファイルをアップロードしています。一応 Metadata も設定していますが、今回は使っていないので不要です。

送信ボタンのハンドラの一部
        if (!_self.state.file.name.match(/^[0-9a-zA-Z\.\_\-]*$/)) {
            handleErrorFunc('エラー:ファイル名は小文字の英数字と . - _ しか使えません: '+_self.state.file.name );
            return;
        }
        filename = 'contents/images/'+identityId+'/'+_self.state.file.name;
        fileType = _self.state.file.type;
        var params = {
            Bucket: bucketname,
            Key: filename,
            ContentType: _self.state.file.type,
            Body: _self.state.file,
            Metadata: {
              data: JSON.stringify({
                identityId: identityId,
                uploadTime: uploadTime,
                uploadDate: uploadDate
              })
            }
        };
        var s3 = new AWS.S3();
        s3.putObject(params, function(err, data) {
            if(err) {
                console.log("Err: upload failed :" +err);
            } else {
                console.log("Success: upload ok");
            }
        });

3.画像の参照

 上で作成したfilename変数を使えば、画像は以下のURLで参照できます。実際はfilenameはDynamoDBのテーブルに保存してあるので、そこから取り出してURLを作成することになります。

const imgurl = 'http://'+bucketname+'.s3-'+appConfig.region+'.amazonaws.com/'+filename;

4.画像の削除

 画像の削除も簡単です

削除ボタンのハンドラの一部
        const s3 = new AWS.S3();
        const params1 = {
            Bucket: bucketname,
            Key: item.filename,
        };
        s3.deleteObject(params1, function(err, data) {
          if (err) console.log(err); // an error occurred
          else     console.log("### delete image ok");           // successful response
        });

5.キャッシュファイル

 DynamoDBは課金制ですし、安いスループットに設定しているので、トップページにキャッシュを設けることにしました。これは3番目のS3の使い方になります。

 トップページは常に現在の投稿の一覧を取得し表示してますので、DyanmoDBにqueryを発行しています。この投稿の一覧をJSONファイルとしてS3にキャッシュします。新たな投稿や編集があった場合にキャッシュを削除します。

キャッシュファイルの作成
    var params = {
        Bucket: bucketname,
        Key: cachepath,
        ContentType: 'application/json',
        Body: JSON.stringify(data.Items)
    };
    s3.putObject(params, function(err, data) {
      if (err) console.log("### cache upload error",err, err.stack);
      else     console.log("### cache upload successful"+data);
    });

キャッシュの削除や参照については割愛します。

今回はこれで終わりますが、DynamoDBなどは次回以降に書いていきたいと思います。

24
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
33