v2での作り方は転がってるが、v3での作り方がわからず若干ハマったのでメモ

パッケージインストール

yarn add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

環境

>yarn list --pattern @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
yarn list v1.22.19
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ @aws-sdk/[email protected]
└─ @aws-sdk/[email protected]
Done in 1.13s

対応

BackBlazeB2の keyID をアクセスキーに、applicationKey をシークレットアクセスキーに、バケットのEndpointをエンドポイントに設定して作成する

以下作成したコード

/main.ts
import Client from "./BucketClinet";

const client = new Client(accessKey, secretAccessKey, endpoint);
url = await client.getPreSignedUrl(env.BUCKET_NAME, "public/sample.png");
BucketClient.ts
import { S3Client, S3ClientConfig, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

export default class BucketClient {
  private s3ClientConfig: S3ClientConfig;

  constructor(
    private accessKey: string,
    private secretAccessKey: string,
    private endpoint: string
  ) {
    this.s3ClientConfig = {
      endpoint: { hostname: this.endpoint, protocol: "https", path: "/" },
      // 未指定の場合PreSignedUrlにホスト名が含まれない
      forcePathStyle: true,
      // 未指定の場合エラーになるため指定
      region: "ap-northeast-1",
      credentials: {
        accessKeyId: this.accessKey,
        secretAccessKey: this.secretAccessKey,
      },
    };
  }

  public async getPreSignedUrl(
    bucket: string,
    key: string,
    expiresIn: number = 3600
  ) {
    const bucketParams = {
      Bucket: bucket,
      Key: key,
    };
    const s3Client: S3Client = new S3Client(this.s3ClientConfig);
    const command = new PutObjectCommand(bucketParams);
    return getSignedUrl(s3Client, command, {
      expiresIn: expiresIn,
    });
  }
}
Note
  • S3ClientConfigの region はカスタムエンドポイントを使用する場合でも指定しないとエラーになる

  • S3ClientConfigの forcePathStyle を指定しないとpresigned URLのエンドポイント部分が空になる

確認

vscodeのRestClientで確認

presigned.http
PUT ${PRESIGNED_URL}
content-type: image/png

< ./sample.png