AWS SDK for JavaScript v3 で S3 の操作を行う方法

#はじめに
現在Node.jsでAWSのサービスは「AWS SDK」というパッケージで操作することが可能になっています。
大まかに「v2」「v3」に分かれていて、v3は操作するサービスごとに個別にパッケージをインストールすることができたりTypescriptのサポートを進めたことから公式もv3の使用を推奨しているようです。
しかし、現状情報はv2の情報が多いこと、v2とv3で違いが大きかったりして使用する際にハマったことが多かったこと、また公式ドキュメントも正直わかりづらく情報を得るのに苦戦したので、v3でS3を操作する方法をここに記したいと思います。

#パッケージのインストール
前述したようにv3は操作するサービスごとに個別にパッケージをインストールできるので、S3を操作するパッケージをインストールします。

###npm 
```
npm i -S @aws-sdk/client-s3
```

###yarn 
```
yarn add @aws-sdk/client-s3
```

#S3の操作方法

###１・インスタンスの生成
```javascript
import {S3Client} from '@aws-sdk/client-s3';

const s3 = new S3Client({
  region: 'ap-northeast-1',
  credentials: {
      accessKeyId: 'sample',
      secretAccessKey:'sample',
  },
})
```

###２・バケットの作成

```javascript
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

//S3バケットを作成する
s3.send(
    new CreateBucketCommand({
        Bucket: '作成したいバケット名'
    })
);
```

###３・バケットの削除

```javascript
import { S3Client, DeleteBucketCommand } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

//S3バケットを削除する
s3.send(
    new DeleteBucketCommand({
        Bucket: '削除したいバケット名'
    })
);
```

###４・バケットにオブジェクトを追加

```javascript
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

s3.send(
    new PutObjectCommand({
         Bucket: '保存したいバケット名',
         Key: 'キーを設定。取り出す際はこのキーで参照する',
         Body: '保存したいオブジェクト本体'
    })
)
```

###５・複数のバケット内オブジェクトを取得

```javascript
import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

 await s3.send(
      new ListObjectsV2Command({
        Bucket: 'バケット名',
        MaxKeys: 10, //取得件数を指定。最大1000件まで
      })
 );
```

###６・バケット内の特定のオブジェクトを取得
ここが私が一番苦戦したところでした。
「GetObjectCommand」で取得したオブジェクトは「Result.Body」に格納されているのですが、このオブジェクトは「ReadableStream」オブジェクトになっているためそのままでは取得できません。
「fs.createWriteStream」などで書き込み専用のストリームを定義し、.pipe()メソッドで少しづつデータを渡してあげる必要があります。


```javascript
import fs from 'fs';
import { Readable } from 'stream';
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

 const result = await s3.send(
      new GetObjectCommand({
        Bucket: 'バケット名',
        Key: '取得したいオブジェクトのキー'
      })
 );

const readableObj = result.Body as Readable;

const writableObj = fs.createWriteStream('ファイル名');

//readableObjをwritableObjに少しづつ書き込む
readableObj.pipe(writebleObj);

```

expressの場合は、レスポンスオブジェクトにS3から取得したオブジェクトを.pipe()メソッドで書き込むことが可能です。

```javascript
import fs from 'fs';
import { Readable } from 'stream';

import { Request, Response, Router} from 'express';
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';

//画像を取得するhandler
const getImage = async (req: Request, res: Response) => {

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

const result = await s3.send(
      new GetObjectCommand({
        Bucket: 'バケット名',
        Key: '取得したいオブジェクトのキー'
      })
 );

const readableObj = result.Body as Readable;

res.setHeader('Content-Type', 'image/png');
res.setHeader('Content-Length', result.ContentLength as number);

//readableObjをresに少しづつ書き込む
readableObj.pipe(res);

}

const router = Router();

router.get('/image/get', getImage);


```



###７・バケット内のオブジェクトを削除する

```javascript
import { S3Client, DeleteObjectCommand } from '@aws-sdk/client-s3';

const s3 = new S3Client({
      region: 'ap-northeast-1',
      credentials: {
          accessKeyId: 'sample',
          secretAccessKey:'sample',
      },
});

await s3.send(
    new DeleteObjectCommand({
        Bucket: 'バケット名',
        Key: '削除したいオブジェクトのキー'
    })
);
```

#まとめ

今回はAWSSDKのV3でS3の操作をする方法を紹介しました。
今後も随時情報を更新していきます。