まくろぐ

Node.js で Amazon S3 を操作する (AWS SDK)

更新:
作成:

ここでは、Node.js 用の AWS SDK を使って Amazon S3 を操作する方法を説明します。 TypeScript の基本的な環境構築 は終わっているものとします。

S3 用の Node.js SDK をインストールする

AWS SDK version 3 の S3 用パッケージをインストールするには次のようにします。

$ npm install @aws-sdk/client-s3 --save

これで、TypeScript コードから次のようにパッケージ内のクラスをインポートできるようになります。

main.ts
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';

S3Client インスタンスの生成

AWS SDK で S3 の操作を行うには、S3Client オブジェクトを使って各種コマンドを送ります。

new S3Client(configuration: S3ClientConfig): S3Client

S3Client コンストラクタには S3ClientConfig オブジェクトを渡すようになっており、接続情報などを指定できます。 空オブジェクト ({}) を渡すと、現在の環境の default プロファイルの設定が使用されます(~/.aws/config~/.aws/credentials に設定されたもの)。

// default プロファイルで接続する場合
const s3 = new S3Client({});

// 接続情報をカスタマイズする場合
const s3 = new S3Client({
  region: 'ap-northeast-1',
  credentials: {
    accessKeyId: 'QABCSCRHWJAKIAQXINMC',
    secretAccessKey: 'TTey3DVmbrILhTforDDa8kR6+SL+47htmoJ+Vimv',
  },
});

一時的にプロファイルを切り替えて実行したいときは、環境変数 AWS_PROFILE でプロファイル名を指定します。

例: プロファイルを admin に切り替えて実行
$ export AWS_PROFILE=admin
$ npm start --silent

設定情報を確認する

次のようにすれば、S3Client のコンフィギュレーション情報として、どのような設定が使用されるかを確認できます。

main.ts
import { S3Client } from '@aws-sdk/client-s3';

const s3 = new S3Client({});
(async () => {
  console.log(await s3.config.credentials());
  console.log(await s3.config.endpoint());
})();
{
  accessKeyId: 'QAGPX77PNSAKIAQXINMC',
  secretAccessKey: 'FegIdbCW2JK7Jiv9yfZGGH3Q2KAmp2ufOANToPDX',
  sessionToken: undefined
}
{
  hostname: 's3.ap-northeast-1.amazonaws.com',
  port: undefined,
  protocol: 'https:',
  path: '/',
  query: undefined
}

S3 バケットを作成する (CreateBucketCommand)

新しい S3 バケットを作成するには、S3Client#send() メソッドで CreateBucketCommand コマンドを送ります。

create-bucket.ts
import { S3Client, CreateBucketCommand, } from '@aws-sdk/client-s3';
const s3 = new S3Client({});

// S3 バケットを作成する
async function createBucket() {
  try {
    const output = await s3.send(
      new CreateBucketCommand({
        Bucket: 's3-123456789012-sample-bucket-1'
      })
    );
    console.log('SUCCESS - Bucket created:', output);
  } catch (err) {
    console.error('ERROR:', err);
  }
}

createBucket();
SUCCESS - Bucket created: {
  '$metadata': {
    httpStatusCode: 200,
    requestId: undefined,
    extendedRequestId: 'X8LD9DYz4+UB8MbbwdfuH2nifmfLC0qJt0LcGhpRAZUDOBAYtrk/qsVqc/WLtYQj7qbIPmIk3gj=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  Location: 'http://s3-123456789012-sample-bucket-1.s3.amazonaws.com/'
}

S3 バケットを削除する (DeleteBucketCommand)

S3 バケットを削除するには、S3Client#send() メソッドで DeleteBucketCommand コマンドを送ります。 バケットを削除するには、先にバケット内のオブジェクトをすべて削除しておく必要があります。

delete-bucket.ts
import { S3Client, DeleteBucketCommand, } from '@aws-sdk/client-s3';
const s3 = new S3Client({});

// S3 バケットを削除する(先にすべてのオブジェクトを削除しておく必要あり)
async function deleteBucket() {
  try {
    const output = await s3.send(
      new DeleteBucketCommand({
        Bucket: 's3-123456789012-sample-bucket-1'
      })
    );
    console.log('SUCCESS - Bucket deleted:', output);
  } catch (err) {
    console.error('ERROR:', err);
  }
}

deleteBucket();
SUCCESS - Bucket deleted: {
  '$metadata': {
    httpStatusCode: 204,
    requestId: undefined,
    extendedRequestId: 'Ha4qd+x3FHsbi8WsdRu9GTXz5LhLl3s/m/yavxT6Nc9LOgjKNCG2Plk19V86hdeTyfKws6jfFF/=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  }
}

S3 バケットにオブジェクトを追加する (PutObjectCommand)

既存の S3 バケットにオブジェクトを追加するには、S3Client#send() メソッドで PutObjectCommand コマンドを送ります。

put-object.ts
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({});

// S3 バケットにオブジェクトを追加する
async function putObject() {
  try {
    const output = await s3.send(
      new PutObjectCommand({
        Bucket: 's3-123456789012-sample-bucket-1',
        Key: 'object-key-1',
        Body: 'object-body-1'
      })
    );
    console.log('SUCCESS - Object added:', output);
  } catch (err) {
    console.error('ERROR:', err);
  }
}

putObject();
SUCCESS - Object added: {
  '$metadata': {
    httpStatusCode: 200,
    requestId: undefined,
    extendedRequestId: 'M0oachGF8zXfHPrFA97PO2LNz/9dkinNBeCUz4vhaQLeorIdGkmLFqMAkhdhuEb1s9iu4JIC947=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  BucketKeyEnabled: undefined,
  ETag: '"f0d3e2d98146efec4959d6bf45924b7e"',
  Expiration: undefined,
  RequestCharged: undefined,
  SSECustomerAlgorithm: undefined,
  SSECustomerKeyMD5: undefined,
  SSEKMSEncryptionContext: undefined,
  SSEKMSKeyId: undefined,
  ServerSideEncryption: undefined,
  VersionId: undefined
}

(おまけ)SDK V2 の場合

put-object-v2.ts
import * as AWS from 'aws-sdk';
const s3 = new AWS.S3({ region: 'ap-northeast-1' });

async function putObjectV2() {
  try {
    const output = await s3.putObject({
      Bucket: 's3-123456789012-sample-bucket-1',
      Key: 'object-key-1',
      Body: 'object-body-1'
    }).promise();
    console.log('SUCCESS - Object added:', output);
  } catch (err) {
    console.error('ERROR:', err);
  }
}

putObjectV2();
実行結果 (SDK V2)
SUCCESS - Object added: { ETag: '"90ad571f0ce74c38c7eca7a806a7ce68"' }

S3 バケット内のオブジェクトの一覧を取得する (ListObjectV2Command)

S3 バケット内のオブジェクトのリスト(最大1000件)を取得するには、S3Client#send() メソッドで ListObjectsV2Command コマンドを送ります。

list-objects.ts
import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3';
const s3 = new S3Client({});

// S3 バケット内のオブジェクトの一覧を取得する
async function listObjects() {
  try {
    const output = await s3.send(
      new ListObjectsV2Command({
        Bucket: 's3-123456789012-sample-bucket-1',
        MaxKeys: 10,  // 最大10件まで取得
      })
    );
    for (const obj of output.Contents || []) {
      console.log(obj);
    }
  } catch (err) {
    console.error('ERROR:', err);
  }
}

listObjects();
{
  Key: 'object-key-1',
  LastModified: 2021-03-21T07:51:13.000Z,
  ETag: '"59d6bf45924b7ef0d3e2d98146efec49"',
  Size: 13,
  StorageClass: 'STANDARD',
  Owner: undefined
}
{
  Key: 'object-key-2',
  LastModified: 2021-03-21T08:12:11.000Z,
  ETag: '"3f895677e156d30464cb71606a3f0f46"',
  Size: 13,
  StorageClass: 'STANDARD',
  Owner: undefined
}
{
  Key: 'object-key-3',
  LastModified: 2021-03-21T08:12:18.000Z,
  ETag: '"a4d8c2240f532047c257f1208dd710c2"',
  Size: 13,
  StorageClass: 'STANDARD',
  Owner: undefined
}

オブジェクトの内容を取得する (GetObjectCommand)

特定のオブジェクトの内容を取得するには、S3Client#send() メソッドで GetObjectCommand コマンドを送ります。

戻り値の GetObjectCommandOutputBody プロパティを参照すると、バケットオブジェクトの内容を取得できるのですが、これは Readable オブジェクト(Stream のサブインタフェース)になっているため、少しずつデータを取り出して結合する必要があります。

get-object.ts
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import { Stream } from 'stream';
const s3 = new S3Client({});

// GetObjectCommandObject の Body 要素 (Readable) からテキストを取得
function streamToString(stream: Stream) {
  const buf: Buffer[] = [];
  return new Promise((resolve, reject) => {
    stream.on('data', chunk => buf.push(Buffer.from(chunk)));
    stream.on('error', err => reject(err));
    stream.on('end', () => resolve(Buffer.concat(buf).toString('utf-8')));
  })
}

// 指定したオブジェクトの内容を取得する
async function getObject() {
  try {
    const output = await s3.send(
      new GetObjectCommand({
        Bucket: 's3-123456789012-sample-bucket-1',
        Key: 'object-key-1'
      })
    );
    const text = await streamToString(output.Body as Stream);
    console.log(text);
  } catch (err) {
    console.error('ERROR:', err);
  }
}

getObject();
実行結果
object-body-1

(おまけ)SDK V2 の場合

get-object-v2.ts
import { S3 } from 'aws-sdk';
const s3 = new S3();

async function getS3Object(): Promise<string | undefined> {
  const output: S3.GetObjectOutput = await s3.getObject({
    Bucket: 's3-123456789012-sample-bucket-1',
    Key: 'object-key-1',
  }).promise();

  return output.Body?.toString();
}

(async function main() {
  const body = await getS3Object();
  console.log(body);
})();
実行結果 (SDK V2)
object-body-1

関連記事

まくろぐ
サイトマップまくへのメッセージ