どうも、駆け出し12冠エンジニアのアスカです。Amplify Gen2がGAしてドキュメントのStorage機能に関する部分が充実していたので、それを参考にしながら触ってみます!
Amplify Gen2のドキュメント
想像以上にボリュームがあったので、連載の形をとろうかと思います。今回は1つ目の最初のアップロードまでやっていきます。
- 最初のアップロードまで
- 認証ルールの設定
- ファイルのアップロード
- ファイルのダウンロード
- ファイルプロパティの取得
- ファイルの削除
- ファイルのコピー
- ファイルイベントの取得
事前準備
ドキュメントのQuickStartを参考にプロジェクトを作成します。
参考:Amplify Gen2がGAしたので再Quickstartしてみた
Amplifyの機能部分は以下のフォルダ構成が作られます。
├── amplify/
│ ├── auth/
│ │ └── resource.ts
│ ├── data/
│ │ └── resource.ts
│ ├── backend.ts
│ └── package.json
├── node_modules/
├── .gitignore
├── package-lock.json
├── package.json
└── tsconfig.json
参考に挙げたブログで構築した環境をスタートラインとして、Storage機能を触っていきます。
最初のアップロードまでの流れ
こんな流れでやっていきます。
- バックエンドストレ-ジを定義
- ストレージへのアクセス権限を定義
- ファイルをアップロードしてみる
バックエンドにストレージを定義
amplify/storage/resource.tsを作成して以下のコードを記述します。
import { defineStorage } from '@aws-amplify/backend';
export const storage = defineStorage({
name: 'amplifygen2Test'
});
ここではdefineStorage関数でストレージを定義してエクスポートしています。
name要素は好きな名前を入れてOKです。(実装はAmplifyがUUIDを付けてグローバルで一意にしてくれます)
次にamplify/backend.tsを以下のように修正して、ストレージをインポートします。すでに認証とデータベース部分は作成しているので、そこにストレージも追加する形ですね。
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
+ import { storage } from './storage/resource';
defineBackend({
auth,
data,
+ storage,
});
ストレージへのアクセス権限を定義
これまでのステップでストレージとしてS3バケットは作成出来ましたが、デフォルトでは誰もアクセス出来ない状態なので、defineStorageと同時にアクセス権限も定義してあげる必要があります。
ここでは以下にような設定を行います。
- 全てのユーザは全ての写真の閲覧が可能だが、プロフィール写真をアップロードしたユーザーのみがその変更、削除が出来る。この場合、ユーザはIdentity Pool IDによって識別される。
- 全てのユーザが写真を投稿できる一般的なプールも存在。
import { defineStorage } from '@aws-amplify/backend';
export const storage = defineStorage({
name: 'amplifygen2Test',
+ access: (allow) => ({
+ 'profile-pictures/{entity_id}/*': [
+ allow.guest.to(['read']),
+ allow.entity('identity').to(['read', 'write', 'delete'])
+ ],
+ 'picture-submissions/*': [
+ allow.authenticated.to(['read','write']),
+ allow.guest.to(['read', 'write'])
+ ],
+ })
});
ファイルをアップロードしてみる
ドキュメントでは以下のコードをApp.tsxに追加し、アップロードボタンを作成しますが。ビルドで失敗しました。TypeScriptの型チェックでエラーが発生したようです。
import React from 'react';
import { uploadData } from 'aws-amplify/storage';
function App() {
const [file, setFile] = React.useState();
const handleChange = (event: any) => {
setFile(event.target.files[0]);
};
return (
<div>
<input type="file" onChange={handleChange} />
<button
onClick={() =>
uploadData({
path: `picture-submissions/${file.name}`,
data: file,
})
}
>
Upload
</button>
</div>
);
}
上記のコードでは、inputファイルが変更される度にhandleChangeが呼び出されてfile変数にファイルが格納され、uploadボタンを押すとuploadData関数が呼び出されてファイルがアップロードされるようになっています。ただし、このままではfileが"undefined"の可能性もあるため、TSのビルド時にエラーが発生します。以下のようにfileが"undefined"ではない事を確認してからアップロード処理する事でエラーを回避出来ます。
import React from 'react';
import { uploadData } from 'aws-amplify/storage';
function App() {
const [file, setFile] = useState<File | undefined>();
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files;
if (files) {
setFile(files[0]);
}
};
const handleUpload = () => {
if (file) { // file が undefined でないことを確認
uploadData({
path: `picture-submissions/${file.name}`,
data: file,
})
alert(`${file.name}がアップロードされました。`)
} else{
alert(`ファイルが選択されていません。`)
};
};
return (
<div>
<input type="file" onChange={handleChange} />
<button
onClick={handleUpload}>
Upload
</button>
</div>
);
}
一番大きな変更はhandleUpload関数を追加した部分で、関数内部でfileが"undefined"ではないか確認します。
下画像のようなアップロードボタンの作成が出来て、画像をアップロード出来る事を確認しました。
※ 雑にTodoアプリに追加してしまっていますが許してください笑
感想&まとめ
今回はAmplify Gen2のストレ-ジ機能をドキュメントに沿って触ってみました。
データベース同様、簡単にリソースの定義とパス毎のアクセス権限を付与する事が出来ました。色々な事がCDKベースで簡単に実現出来そうでワクワクしますね!
引き続きAmplifynGen2の機能を触っていきたいと思います!!