🎢
AWS SDK for JavaScript v3 で S3 への Stream Upload を試した
モチベ
- 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 は ブラウザ向けという雑な理解で一旦置いておく)
参考資料
Discussion