[アップデート] AWS Amplify Gen 2 の Storage で複数バケットがサポートされたので使ってみた

[アップデート] AWS Amplify Gen 2 の Storage で複数バケットがサポートされたので使ってみた

Clock Icon2024.09.08

いわさです。

先月になりますが、AWS Amplify でストレージ機能で複数バケットがサポートされるというアップデートがありました。

https://aws.amazon.com/about-aws/whats-new/2024/08/aws-amplify-multiple-bucket-storage/

Amplify (Gen 2) では defineStorage でストレージバケットの定義ができるのですが、以前までは複数の defineStorage 追加は出来ませんでした。
回避策としてスタックに直接バケットを追加してやる方法はあったのですが、Storage API 経由でアクセスする場合などちょっと利用の際も面倒でした。

今回のアップデートで defineStorage が複数定義できるようになり、さらに Storage API 側でも定義されたストレージ名を指定して対象バケットを指定したアクセスが可能です。
プルリクエストは以下です。2024 年 8 月上旬に取り込まれています。

https://github.com/aws-amplify/amplify-backend/pull/1742

従来どおりの単一ストレージの定義

Amplify Gen 2 でストレージを使う場合は以下のセットアップ手順に従うことで開始出来ます。

https://docs.amplify.aws/react/build-a-backend/storage/set-up-storage/

バックエンドリソースの定義は次の様な感じです。

amplify/storage/resource.ts
import { defineStorage } from '@aws-amplify/backend';

export const bucket1 = defineStorage({
  name: 'hoge0908bucket1',
  access: (allow) => ({
    'publichoge/*': [allow.authenticated.to(['list'])],
  })
});

利用側は次のような感じで、これまでは一つだったのでどのバケットなのか特に意識する必要はありませんでした。
パスでどうにかしていた感じです。

app/page.tsx
"use client"
import { Amplify } from 'aws-amplify';
import outputs from "../amplify_outputs.json";

Amplify.configure(outputs);

import React, { useEffect, useState } from 'react';
import { list } from "aws-amplify/storage";
import { Authenticator } from '@aws-amplify/ui-react';

export default function Hoge() {

  const [fileList, setFileList] = useState<string[]>([]);
  useEffect(() => {
    (async () => {
      const response = await list({
        path: 'publichoge/',
      });
      setFileList(response.items.map((item) => item.path));
    })();
  }, []);

  return (
    <Authenticator>
      {({ signOut, user }) => (
        <div>
          <h2>File List</h2>
          <ul>
            {fileList.map((key, _i) => (
              <li>
                <div>
                  <p>{key}</p>
                </div>
              </li>
            ))}
          </ul>
        </div>
      )}
    </Authenticator>
  );
}

上記コードだと、次のように S3 バケットにファイルが格納されている状態で画面にオブジェクトパスをリスト表示します。

A6D9EC4A-D0FB-4B76-8A4D-E14AA2EC659A.png

こんな感じになります。

41886F7E-DB7D-4293-86CC-0C1F99C5A817_4_5005_c.jpeg

今回のアップデート後もストレージがひとつのみであればこのままの実装で問題ありません。
そのためアップデートによる既存コードの変更は不要です。

マルチバケット

複数ストレージを使う場合についてはコードの変更が必要になります。試してみましょう。
まずはバックエンド定義から。

バックエンドは追加で defineStorage する

基本的には追加で defineStorage を追加してやるだけです。
これごとに S3 バケットが作成されます。

amplify/storage/resource.ts
import { defineStorage } from '@aws-amplify/backend';

export const bucket1 = defineStorage({
    name: 'hoge0908bucket1',
    access: (allow) => ({
      'publichoge/*': [allow.authenticated.to(['list'])],
    })
  });

export const bucket2 = defineStorage({
    name: 'hoge0908bucket2',
    access: (allow) => ({
      'publichoge/*': [allow.authenticated.to(['list'])],
    })
  });

ただし、このままだと NG で、バックエンドデプロイ時にエラーとなります。

No default storage set in the Amplify project.
Resolution: Add `isDefault: true` to one of the `defineStorage` calls in your Amplify project.

今回のアップデートでストレージにisDefaultというデフォルトストレージを示すプロパティが追加され、複数バケットが定義されている場合はどれかひとつをデフォルトストレージとして指定する必要があります。

今回はhoge0908bucket2というストレージを追加し、こいつをデフォルトに指定してみましょう。

amplify/storage/resource.ts
import { defineStorage } from '@aws-amplify/backend';

export const bucket1 = defineStorage({
    name: 'hoge0908bucket1',
    access: (allow) => ({
      'publichoge/*': [allow.authenticated.to(['list'])],
    })
  });

export const bucket2 = defineStorage({
    name: 'hoge0908bucket2',
    isDefault: true,
    access: (allow) => ({
      'publichoge/*': [allow.authenticated.to(['list'])],
    })
  });

ちなみにisDefaultで指定したストレージが Outputs のbucket_nameとなり、bucketsには複数バケットが設定されていました。なるほどね。

amplify_outputs.json
{

:

  "storage": {
    "aws_region": "ap-northeast-1",
    "bucket_name": "amplify-myapp-iwasatakahi-hoge0908bucket2bucket6d7-m0dga9ormsz6",
    "buckets": [
      {
        "name": "hoge0908bucket1",
        "bucket_name": "amplify-myapp-iwasatakahi-hoge0908bucket1bucket2e9-148xv93gekzf",
        "aws_region": "ap-northeast-1"
      },
      {
        "name": "hoge0908bucket2",
        "bucket_name": "amplify-myapp-iwasatakahi-hoge0908bucket2bucket6d7-m0dga9ormsz6",
        "aws_region": "ap-northeast-1"
      }
    ]
  },
  "version": "1.1"
}

フロントエンドは Storage API でバケットを指定できる

そして Storage API の利用側は、どのストレージを使うのかを指定できます。
省略した場合は先ほどのデフォルトストレージが使われるようで、今回だと次のようにhoge0908bucket2の内容が表示されました。

374D901D-ACB1-4365-9778-8FBB91B1E724_4_5005_c.jpeg

デフォルト以外を指定したい場合はオプションで指定します。

app/page.tsx
:

export default function Hoge() {

  const [fileList, setFileList] = useState<string[]>([]);
  useEffect(() => {
    (async () => {
      const response = await list({
        path: 'publichoge/',
        options: {
          bucket: "hoge0908bucket1"
        },
      });
      setFileList(response.items.map((item) => item.path));
    })();
  }, []);

:

41886F7E-DB7D-4293-86CC-0C1F99C5A817_4_5005_c.jpeg

良いですね。期待どおり指定したバケット内容が表示されました。

さいごに

本日は AWS Amplify Gen 2 の Storage で複数バケットがサポートされたので使ってみました。

今回複数バケットを扱いたいユースケースもサポートされたので、スタックで追加して頑張っていた方は利用できるか再検討してみてください。

この機能リクエスト、Issue 起票からプルリクエスト取り込みまで中々のスピード感なので、Amplify Gen 2 の機能強化の速さを感じました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.