🎢

AWS SDK for JavaScript v3 で S3 への Stream Upload を試した

2023/04/21に公開

モチベ

  • AWS SDK for JavaScript (v2) は 2023年にメンテナンスモードに入る
  • 今後は v3 を利用していくのが良さそう
  • 個人開発で使うので v3 かつ Stream で S3 へのアップロードを試してみる

試した内容

  • Node.js 環境(サーバーサイド想定)
  • 指定のURLから画像ファイルを Stream でダウンロード
  • S3 へ Stream でアップロード

サンプルコード

import { S3Client } from "@aws-sdk/client-s3";
import { Upload } from "@aws-sdk/lib-storage";
import { Readable } from "node:stream";
import axios from "axios";

export const uploadFromUrlToS3 = async (
  s3client: S3Client,
  url: string,
  key: string,
): Promise<void> => {
  try {
    console.log("Downloading file...");
    const response = await axios.get(url, { responseType: "stream" });
    const fileStream: Readable = response.data;

    const upload = new Upload({
      client: s3client,
      params: {
        Bucket: `${process.env.AWS_S3_BUCKET}`, 
        Key: key,
        Body: fileStream,
        ContentType: "image/jpg",
      },
    });

    console.log("Uploading to S3...");
    await upload.done();

    console.log("Upload successful!");
  } catch (e) {
    console.error(e);
  }
};

node-fetch を使おうかと思ったが、ReadableStream の扱い周りが煩雑になりそうだったので、axios で甘えた

テストコード

import { test } from 'vitest'
import { uploadFromUrlToS3 } from "./upload";
import { S3Client } from "@aws-sdk/client-s3";

test('uploadFromUrlToS3', async () => {
  require('dotenv').config()

  const s3client = new S3Client({
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID || '',
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || ''
    }
  })

  const uploadedFilename = new Date().toISOString().replace(/:/g, '-')

  await uploadFromUrlToS3(
    s3client,
    'https://pbs.twimg.com/profile_images/1612971754489778177/ZsuW-mWs_400x400.jpg',
    `test/${uploadedFilename}.jpg`
  )
})

学び

  • v2 と v3 は異なる repository で管理されている
  • Stream でアップロードしたい場合は、S3Client.send(PutObjectCommand) を使うのではなく @aws-sdk/lib-storage の Upload を使う(lib-storage は 並列アップロードも対応しているみたいで基本これを使っていけばよさそう)
  • Stream 関連のTypeの理解が足りていないことに気づいたので改めて理解したい(Readable は Node.js向け、ReadableStream は ブラウザ向けという雑な理解で一旦置いておく)

参考資料

https://github.com/aws/aws-sdk-js
https://github.com/aws/aws-sdk-js-v3
https://dev.classmethod.jp/articles/aws-sdk-for-javascript-v2-v3-diff/
https://stackoverflow.com/questions/69884898/how-to-upload-a-stream-to-s3-with-aws-sdk-v3

Discussion