Amazon S3

2020年12月27日

はじめに

Amazon S3 のメモ。

バケットの作成

S3 は「バケット」というものを作ってその中にデータを入れる形で利用する。

  1. [バケットの作成] をクリック。
  2. 名前とリージョンの設定。バケット名を入力。バケット名は、全リージョン内でユニークで 3〜63 文字の名前をつける必要がある。
  3. [次へ]。
  4. オプションの設定。よくわからなければ [次へ]。
  5. ブロックパブリックアクセス。"パブリックアクセスをすべてブロック" にチェックがついていることを確認。[次へ]。
  6. 確認。[バケットを作成]。

AWS CLI

バケットの表示

>aws s3 ls

バケットの中身の表示

>aws s3 ls s3://(バケット名)

アップロード

>aws s3 cp sample.csv s3://(バケット名)/sample.csv

フォルダという実体は扱えないが、概念は扱えるようである。フォルダが必要な場合は、作成なしにいきなりパスを入れてしまえばよい。

>aws s3 cp sample.csv s3://(バケット名)/(フォルダ名)/sample.csv

フォルダ内の更新されたファイルだけをアップロードしたい場合は、次のようにする。

>aws s3 sync (フォルダ名) s3://(バケット名)/(フォルダ名)

ダウンロード

>aws s3 cp s3://(バケット名)/sample.csv sample.csv

フォルダの内容をダウンロード

>aws s3 cp s3://(バケット名)/(フォルダ名)/ (フォルダ名)/ --recursive

フォルダの中にフォルダを含んでも、フォルダの内容を丸ごとダウンロードするなら "--recursive" は必要。

削除

>aws s3 rm s3://(バケット名)/(フォルダ名)/sample.csv

フォルダを削除する場合は、"--resursive" オプションをつける。

>aws s3 rm s3://(バケット名)/(フォルダ名) --recursive

AWS SDK for JavaScript

AWS SDK for JavaScript を使うには HTML で次のように書いておく。

<script src="https://sdk.amazonaws.com/js/aws-sdk-2.528.0.min.js"></script>

スクリプトで S3 バケットにアクセスするには、次のようにする。

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  params: {Bucket: '(バケット名)'}
});

実際のアクセスでは、パブリックアクセスを許可するか、認証に応じたポリシーの設定が必要。

また、必要に応じて CORS の設定もいる。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>ETag</ExposeHeader>
    </CORSRule>
</CORSConfiguration>

バケット内のリストの取得

s3.listObjects({}, (err, data) => {
  data.Contents.map((path) => {
    console.log(path.Key);
  });
});

バケット直下のファイルとフォルダのリストの取得

s3.listObjects({Delimiter: "/"}, (err, data) => {
  data.Contents.map((path) => {
    console.log(path.Key);
  });
  data.CommonPrefixes.map((path) => {
    console.log(path.Prefix);
  });
});

フォルダ内のリストの取得

s3.listObjects({Prefix: "folder/"}, (err, data) => {
  data.Contents.map((path) => {
    if (path.Key !== "folder/") {
      console.log(path.Key);
    }
  });
});

フォルダ直下のファイルとフォルダのリストの取得

s3.listObjects({Prefix: "folder/", Delimiter: "/"}, (err, data) => {
  data.Contents.map((path) => {
    if (path.Key !== "folder/") {
      console.log(path.Key);
    }
  });
  data.CommonPrefixes.map((path) => {
    console.log(path.Prefix);
  });
});

データの取得

 s3.getObject({Key: "file.png"}, function(err, file) {
  if (err) {
    console.log("Error: " + err);
  } else {
    console.log(file.Body);
  }
});

JSON ファイルの取得

s3.getObject({Key: "file.json"}, function(err, file) {
  if (err) {
    console.log("Error: " + err);
  } else {
    const data = JSON.parse(file.Body.toString());
    console.log(data);
  }
});

更新時刻の確認

file.LastModified で更新時刻が得られる。更新時刻からどのくらい経っているか知りたければ、Date.now() - file.LastModified で経過時間がミリ秒単位で得られる。

ファイルのアップロード

const params = {
  Key: "folder/file.txt",
  Body: file
}

s3.upload(params, function(err, data) {
  if (err) {
    alert(`Error: ${err.message}`);
  }
});

署名つき URL

一時的にファイルを公開したい場合には、署名つき URL が使える。

const params = {
  Key: "(ファイル名)",
  Expires: 60
};

s3.getSignedUrl("getObject", params, function(err, url) {
    console.log("The URL is", url);
});

ただし、HLS のように実体が複数ファイルから構成されるものではうまくいかない。

Canvas の絵を保存する

function writeImage(name, data) {
  const binary = atob(data);

  const array = [];
  for(let i = 0; i < binary.length; i++) {
    array.push(binary.charCodeAt(i));
  }

  const params = {
    Key: 'canvas.png',
    Body: new Uint8Array(array)
  };
  
  s3.putObject(params, function(err, data) {
    if (err) {
      alert(`エラー: ${err.message}`);
    }
  });
}

const image = canvas.toDataURL().replace(/^.*,/, "");
writeImage(name, image);