本記事では、Node.js、TypeScript、aws-sdkを使用してファイル生成およびS3へのアップロード処理を実装する方法について備忘録としてまとめていきます。
実装手順には、下記内容が含まれますので、基本的な内容がメインとなります。
- 必要なライブラリのインストール
- ファイル生成およびS3へのアップロード処理の実装
開発環境
- Node.js:
v16.18.1
- npm:
v8.19.2
- TypeScript:
v4.9.5
実装の流れ
前回の記事を参考に構築
aws-sdkなど今回の実装に必要なライブラリをインストール
アップロード用のJSONファイルを生成
aws-sdkを使ってS3に対する操作処理を実装
MinIOを使って実際にアップロードできているか検証
アップロード以外の操作方法を紹介
実装手順
実行環境の構築
今回の実装を進めていくにあたって下記2点を準備する。
- Node.js + TypeScriptによる実行環境の構築
- ローカル環境用のS3をMinIOを使って構築
すでに構築済みの場合はスキップしても問題ないですが、過去記事で構築した状態から実装開始される点には注意
Node.js + TypeScriptによる実行環境の構築
ローカル環境用のS3をMinIOを使って構築
上記完了後のディレクトリ構成は以下
.
├── README.md
├── minio
│ └── data
│ └── sample
├── dist
│ └── index.js
├── src
│ ├── index.ts
├── docker-compose.yml
├── package-lock.json
├── package.json
└── tsconfig.json
ライブラリのインストール
下記ライブラリをインストールしていきます。
@aws-sdk/client-s3
:AWS S3との疎通を行うためのNode.jsオフィシャルクライアント@aws-sdk/credential-providers
:AWS認証情報の取得を簡単にするために利用cdate
:軽量かつ速い、そして使いやすい日付操作ライブラリ
https://github.com/kawanet/cdate
moment.js・day.js よりも速くて軽い cdate ライブラリts-dotenv
:TypeScript用の.envファイルの簡単な読み込みをサポート
$ npm i cdate
$ npm i -D @aws-sdk/client-s3 @aws-sdk/credential-providers ts-dotenv
"devDependencies": {
"@aws-sdk/client-s3": "^3.282.0",
"@aws-sdk/credential-providers": "^3.282.0",
"@types/node": "^16.18.12",
"ts-dotenv": "^0.9.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
},
"dependencies": {
"cdate": "^0.0.4"
}
ファイル生成処理の実装
S3へアップロードするためのファイルを生成していきます。
今回は簡単なJSONデータを生成し、それをファイルとしてアップロードしていきます。
処理フロー
- JSONデータ内に含める日付情報を生成
- JSONに含めるための
data
オブジェクトを生成 JSON.stringify
を利用して、オブジェクトをJSON形式の文字列に変換
index.tsにJSONデータの生成処理を実装
import { cdate } from 'cdate';
(async () => {
//JSONデータの生成
const currentDate = cdate().format('YYYYMMDDHHmmss');
const data = {
title: 'Hello World!!!',
date: currentDate,
};
const json = JSON.stringify(data);
})();
S3へのアップロード処理実装
処理フロー
- JSONデータとファイル名に付与する日付情報を
uploadObject
に渡す - 指定したプロファイルやエンドポイントを元に
S3Client
を作成 S3Client
に渡すパラメータをinputParams
にまとめるPutObjectCommand
を使用して対象のバケットへファイルをアップロード- アップロード完了後、レスポンスで受け取った
ETag
情報も加えてログへ出力
index.ts
にアップロード処理を実装
import { cdate } from 'cdate';
import { load } from 'ts-dotenv';
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { fromIni } from '@aws-sdk/credential-providers';
const env = load({
BUCKET_NAME: String,
AWS_PROFILE: String,
S3_ENDPOINT: String,
});
const s3Client = new S3Client({
credentials: fromIni({ profile: env.AWS_PROFILE }),
endpoint: env.S3_ENDPOINT,
});
const uploadObject = async (body: string, date: string) => {
try {
const inputParams = {
Bucket: env.BUCKET_NAME,
Key: `${date}_sample.json`,
Body: body,
};
const data = await s3Client.send(new PutObjectCommand(inputParams));
console.log(
'Successfully uploaded object: ' +
inputParams.Bucket +
'/' +
inputParams.Key,
'Etag: ' + data.ETag
);
} catch (err) {
console.log('Error', err);
}
};
(async () => {
//JSONデータの生成
const currentDate = cdate().format('YYYYMMDDHHmmss');
const data = {
title: 'Hello World!!!',
date: currentDate,
};
const json = JSON.stringify(data);
//S3アップロード
await uploadObject(json, currentDate);
})();
AWSへの認証については様々な方法が存在しますが、今回はIAMユーザーのアクセスキーとシークレットキーを使用して認証する方法をとっています。
最近はIAMロールを使って認証するのが望ましいと言われていますので、そちらについては別途備忘録としてまとめる予定です。
.env
ファイルに記載する情報
BUCKET_NAME=sample
AWS_PROFILE=minio
S3_ENDPOINT=http://127.0.0.1:9000
MinIO用のAWSプロファイルは事前に設定していることが前提となります。
やり方はコチラ aws-cliを使用してMinIOを操作
動作確認
#MinIOコンテナを起動
$ docker-compose up
$ npm run build
$ node dist/index.js
Successfully uploaded object: sample/20230309231308_sample.json Etag: "999999999999999999999999"
MinIOコンソールにアクセスし、該当ファイルがアップロードされているか確認
無事にアップロードされていることを確認できました。
アップロード以外の処理実装
最後にアップロード処理以外の実装も加えていきたいと思います。
せっかくなので、S3の操作系をまとめてs3-helper.ts
に切り出していきます。
最終的にはこんな感じになりました。
import { load } from 'ts-dotenv';
import {
Bucket,
GetObjectCommand,
ListBucketsCommand,
PutObjectCommand,
S3Client,
} from '@aws-sdk/client-s3';
import { fromIni } from '@aws-sdk/credential-providers';
const env = load({
BUCKET_NAME: String,
AWS_PROFILE: String,
S3_ENDPOINT: String,
});
class S3Helper {
private readonly s3Client: S3Client;
constructor() {
this.s3Client = new S3Client({
credentials: fromIni({ profile: env.AWS_PROFILE }),
endpoint: env.S3_ENDPOINT,
});
}
/**
* バケット一覧の取得
*/
async listBuckets(): Promise<Bucket[] | undefined> {
try {
const data = await this.s3Client.send(new ListBucketsCommand({}));
console.log('Success', data.Buckets);
return data.Buckets;
} catch (err) {
console.log('Error', err);
}
}
/**
* オブジェクトの取得
*/
async getObject(key: string): Promise<string | undefined> {
try {
const bucketParams = {
Bucket: env.BUCKET_NAME,
Key: key,
};
const data = await this.s3Client.send(new GetObjectCommand(bucketParams));
return (await data.Body?.transformToString()) ?? '';
} catch (err) {
console.log('Error', err);
}
}
/**
* オブジェクトのアップロード
*/
async uploadObject(body: string, date: string): Promise<void> {
try {
const bucketParams = {
Bucket: env.BUCKET_NAME,
Key: `${date}_comic_list.json`,
Body: body,
};
const data = await this.s3Client.send(new PutObjectCommand(bucketParams));
console.log(
'Successfully uploaded object: ' +
bucketParams.Bucket +
'/' +
bucketParams.Key,
'Etag: ' + data.ETag
);
} catch (err) {
console.log('Error', err);
}
}
}
export const s3Helper = new S3Helper();
各操作の処理に関しては公式を参考に実装していますので、特別なことはしておりません。
公式Doc
あとは実行ファイル側でs3Helper
をimport
してs3Helper.listBuckets()
と呼び出すだけです。
[補足]AWS認証方法について
AWS-SDKを利用する際のAWS認証方法についてですが、
今回使用したfromIni
とは別の方法として、defaultProvider
を使う方法もあります。
最終的にはIAMロールを利用してアクセスキーやシークレットキーを使わない方法が望ましいので、defaultProvider
を使えばIAMロールでの認証にも対応可能です。
実装手順としては、
@aws-sdk/credential-provider-node
をinstalldefaultProvider
をimportcredentials: defaultProvider()
で認証方法を指定
import { defaultProvider } from '@aws-sdk/credential-provider-node';
const s3Client = new S3Client({
credentials: defaultProvider(),
endpoint: env.S3_ENDPOINT,
});
defaultProviderのソースコードからDefaultProviderInitを見てみると、いくつかの認証方法があります。
export declare type DefaultProviderInit = FromIniInit & RemoteProviderInit & FromProcessInit & FromSSOInit & FromTokenFileInit;
fromIni
で認証する方法も内包されており、認証情報を自動的に取得するため汎用的に利用可能です。
具体的には下記の取得方法があり、下記の優先順位で認証方法が決まるとのこと。
FromProcessInit
: 環境変数からクレデンシャル情報を取得(process.env
経由で公開されたもの)FromSSOInit
: トークンキャッシュからのSSO(Single Sign-On)認証情報を取得(トークンを使用して AWS リソースにアクセス)FromTokenFileInit
: Web Identity トークン認証情報より取得。OpenID Connect (OIDC)
またはOAuth 2.0
認証フローを使用して取得FromIniInit
: ローカルのAWS設定ファイル(通常は~/.aws/credentials
)からクレデンシャルを読み込むRemoteProviderInit
: EC2/ECSインスタンスのメタデータエンドポイントからIAMロールを取得
詳しくは公式Docを参考にしてください。
@aws-sdk/credential-provider-node
まとめ
本記事では、Node.jsとTypeScriptを使用してaws-sdkを利用し、S3へファイルをアップロードする手順を解説しました。
基本的な内容がメインとなりましたので、これをベースに他のユースケースに応じた実装をしていけるかと思います。
毎回実装の度に調べていたので、これでようやく整理できました。
少しでも皆さんの参考になれば幸いです。