🍟

AWS S3 画像アップロード、 React版

2021/12/04に公開

概要:

Reactから、aws S3に画像等のファイルアップロードする例になります。


構成

  • S3: aws Tokyo リージョン
  • react 17
  • node 16

関連

https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/s3-example-photo-album.html

https://qiita.com/akameco/items/277abc7b56cde378f344


準備

  • s3 バケットの作成

  • ACL 有効

  • ブロックパブリックアクセス: 無効にする(ブロックのチェックをOFF)

  • アクセス許可: Cross-Origin Resource Sharing (CORS) 編集

下記jsonデータを、追加

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "HEAD",
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "ETag"
        ]
    }
]

IAM

  • ユーザー追加

  • アクセス権限: AmazonS3FullAccess を追加

  • アクセスキー、シークレットキーをメモする。


  • npm add
npm i --save aws-sdk

アップ機能

  • バケット名、リージョン、アクセスキー、シークレットキー を設定
  • file型の、onChangeイベントで発火して転送

https://gist.github.com/kuc-arc-f/6a7a845376825f61f62c2fbd1f1a6257

Test.tsx
import React from 'react';
import AWS from 'aws-sdk'

const S3_BUCKET ='bucket-name';
const REGION ='ap-northeast-1';

AWS.config.update({
  accessKeyId: 'key123',
  secretAccessKey: 'key123'
})

const myBucket = new AWS.S3({
  params: { Bucket: S3_BUCKET},
  region: REGION,
})
interface IState {
  progress: number,
}
interface IProps {
}

export default class extends React.Component<IProps, IState> {
  // console.log(data.blogs)
    constructor(props: any){
      super(props)
      this.state = {progress: 0};
  //console.log(props )
    }
    componentDidMount(){
      const self = this;
      window.document.getElementById("file1").addEventListener("change", function() {
        console.log("#change");
        self.uploadFile();
      });    
    }
    uploadFile(){
      console.log("uploadFile");
      const files = document.querySelector<HTMLInputElement>('#file1').files;
      const fileObject = files[0]; 
      if (typeof fileObject === "undefined") {
        console.error("none, fileObject");
        return;
      }
      const params = {
        ACL: 'public-read',
        Body: fileObject,
        Bucket: S3_BUCKET,
        Key: fileObject.name
     };      
      myBucket.putObject(params)
      .on('httpUploadProgress', (evt) => {
        console.log(evt.loaded);
        this.setState({
          progress: Math.round((evt.loaded / evt.total) * 100)
        });
      })
      .send((err) => {
          if (err) console.log(err)
      })      
    }
    clickHandler(){
    }
    render(){
      return (
      <div className="body_main_wrap">
        <div className="container"><h1>File Upload test:</h1>
        <hr />
          file : <br />
          <input type="file" name="file1" id="file1" /><br /><br />
          <hr />
          <div>Native SDK File Upload Progress is {this.state.progress}%</div>
        </div>
      </div>
      )
    }
  }

  • 補足

テストの場合、動作確認後にバケットは削除した方が良いです。
(パブリックアクセスは、請求額が増える可能性ありそうです)

....

Discussion