Skip to content

本番サーバーは、ローカルファイルシステムの代わりに S3 互換のオブジェクトストレージサービスにファイルを読み取り、アップロード、および書き込みすることがよくあります。歴史的に、これは開発中に使用するローカルファイルシステム API を本番環境で使用できないことを意味していました。Bun を使用する場合、状況は異なります。

Bun の S3 API は高速です

Bun は S3 互換のオブジェクトストレージサービスと対話するための高速なネイティブバインディングを提供します。Bun の S3 API は、シンプルで fetch の Response および Blob API(Bun のローカルファイルシステム API のような)に似た感覚になるように設計されています。

ts
import { s3, write, S3Client } from "bun";

// Bun.s3 は認証情報の環境変数を読み取ります
// file() は S3 上のファイルへの遅延参照を返します
const metadata = s3.file("123.json");

// S3 から JSON としてダウンロード
const data = await metadata.json();

// S3 にアップロード
await write(metadata, JSON.stringify({ name: "John", age: 30 }));

// URL を事前署名(同期 - ネットワークリクエストは不要)
const url = metadata.presign({
  acl: "public-read",
  expiresIn: 60 * 60 * 24, // 1 日
});

// ファイルを削除
await metadata.delete();

S3 は 事実上の標準 インターネットファイルシステムです。Bun の S3 API は、以下の S3 互換ストレージサービスで動作します:

  • AWS S3
  • Cloudflare R2
  • DigitalOcean Spaces
  • MinIO
  • Backblaze B2
  • ...およびその他の S3 互換ストレージサービス

基本的な使い方

Bun の S3 API を操作するにはいくつかの方法があります。

Bun.S3Client & Bun.s3

Bun.s3new Bun.S3Client() と同等で、認証情報に環境変数を使用します。

認証情報を明示的に設定するには、Bun.S3Client コンストラクターに渡します。

ts
import { S3Client } from "bun";

const client = new S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // sessionToken: "..."
  // acl: "public-read",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
  // endpoint: "https://<region>.digitaloceanspaces.com", // DigitalOcean Spaces
  // endpoint: "http://localhost:9000", // MinIO
});

// Bun.s3 は `new Bun.S3Client()` と同等のグローバルシングルトンです

S3 ファイルの操作

S3Clientfile メソッドは、S3 上のファイルへの遅延参照を返します。

ts
// S3 上のファイルへの遅延参照
const s3file: S3File = client.file("123.json");

Bun.file(path) と同様に、S3Clientfile メソッドは同期です。ネットワークリクエストに依存するメソッドを呼び出すまで、ネットワークリクエストは行われません。

S3 からのファイル読み取り

fetch API を使用したことがある場合、Response および Blob API に慣れているでしょう。S3FileBlob を拡張します。Blob で動作する同じメソッドは S3File でも動作します。

ts
// S3File をテキストとして読み取り
const text = await s3file.text();

// S3File を JSON として読み取り
const json = await s3file.json();

// S3File を ArrayBuffer として読み取り
const buffer = await s3file.arrayBuffer();

// 最初の 1024 バイトのみ取得
const partial = await s3file.slice(0, 1024).text();

// ファイルをストリーム
const stream = s3file.stream();
for await (const chunk of stream) {
  console.log(chunk);
}

メモリ最適化

text()json()bytes()、または arrayBuffer() などのメソッドは、可能な場合、メモリ内の文字列またはバイトの複製を回避します。

テキストが ASCII の場合、Bun は文字列をトランスコードせず、メモリ内で複製せずに JavaScriptCore(エンジン)に直接転送します。.bytes() または .arrayBuffer() を使用する場合も、メモリ内のバイトの複製を回避します。

これらのヘルパーメソッドは API を簡素化するだけでなく、高速化にも役立ちます。

S3 へのファイル書き込みとアップロード

S3 への書き込みも同様に簡単です。

ts
// 文字列を書き込み(ファイルを置き換え)
await s3file.write("Hello World!");

// Buffer を書き込み(ファイルを置き換え)
await s3file.write(Buffer.from("Hello World!"));

// Response を書き込み(ファイルを置き換え)
await s3file.write(new Response("Hello World!"));

// コンテンツタイプ付きで書き込み
await s3file.write(JSON.stringify({ name: "John", age: 30 }), {
  type: "application/json",
});

// ライターを使用して書き込み(ストリーミング)
const writer = s3file.writer({ type: "application/json" });
writer.write("Hello");
writer.write(" World!");
await writer.end();

// Bun.write を使用して書き込み
await Bun.write(s3file, "Hello World!");

大きなファイルの操作(ストリーム)

Bun は大きなファイルのマルチパートアップロードを自動的に処理し、ストリーミング機能を提供します。ローカルファイルで動作する同じ API は S3 ファイルでも動作します。

ts
// 大きなファイルを書き込み
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
const writer = s3file.writer({
  // ネットワークエラー時に最大 3 回自動的に再試行
  retry: 3,

  // 一度に最大 10 リクエストをキュー
  queueSize: 10,

  // 5 MB チャンクでアップロード
  partSize: 5 * 1024 * 1024,
});
for (let i = 0; i < 10; i++) {
  writer.write(bigFile);
  await writer.flush();
}
await writer.end();

URL の事前署名

本番サービスでユーザーがサーバーにファイルをアップロードする必要がある場合、サーバーが仲介役として機能するよりも、ユーザーが直接 S3 にアップロードする方が信頼性が高くなります。

これを容易にするために、S3 ファイルの URL を事前署名できます。これにより、認証情報を公開したり、バケットへの不要なアクセスを許可したりすることなく、ユーザーがその特定のファイルを S3 に安全にアップロードできる署名付き URL が生成されます。

デフォルトの動作は、24 時間で有効期限が切れる GET URL を生成することです。Bun はファイル拡張子からコンテンツタイプを推測しようとします。推測できない場合、デフォルトで application/octet-stream になります。

ts
import { s3 } from "bun";

// 24 時間で有効期限が切れる事前署名 URL を生成(デフォルト)
const download = s3.presign("my-file.txt"); // GET、text/plain、24 時間で有効期限切れ

const upload = s3.presign("my-file", {
  expiresIn: 3600, // 1 時間
  method: "PUT",
  type: "application/json", // 推測するための拡張子がないため、コンテンツタイプを JSON に指定
});

// ファイル参照で .presign() を呼び出すこともできますが、参照を既に持っている場合を除いて避けてください(メモリ使用量を避けるため)。
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
  expiresIn: 3600, // 1 時間
});

ACL の設定

事前署名 URL に ACL(アクセス制御リスト)を設定するには、acl オプションを渡します:

ts
const url = s3file.presign({
  acl: "public-read",
  expiresIn: 3600,
});

以下の ACL を渡すことができます:

ACL説明
"public-read"オブジェクトは公開読み取り可能です。
"private"オブジェクトはバケット所有者のみ読み取り可能です。
"public-read-write"オブジェクトは公開読み取りおよび書き込み可能です。
"authenticated-read"オブジェクトはバケット所有者および認証ユーザーが読み取り可能です。
"aws-exec-read"オブジェクトはリクエストを行った AWS アカウントが読み取り可能です。
"bucket-owner-read"オブジェクトはバケット所有者が読み取り可能です。
"bucket-owner-full-control"オブジェクトはバケット所有者が読み取りおよび書き込み可能です。
"log-delivery-write"オブジェクトはログ配信に使用される AWS サービスが書き込み可能です。

URL の有効期限

事前署名 URL の有効期限を設定するには、expiresIn オプションを渡します。

ts
const url = s3file.presign({
  // 秒単位
  expiresIn: 3600, // 1 時間

  // アクセス制御リスト
  acl: "public-read",

  // HTTP メソッド
  method: "PUT",
});

method

事前署名 URL の HTTP メソッドを設定するには、method オプションを渡します。

ts
const url = s3file.presign({
  method: "PUT",
  // method: "DELETE",
  // method: "GET",
  // method: "HEAD",
  // method: "POST",
  // method: "PUT",
});

new Response(S3File)

S3 ファイルの事前署名 URL にユーザーをすばやくリダイレクトするには、S3File インスタンスを Response オブジェクトの本文として渡します。

これにより、ファイルをサーバーにダウンロードしてユーザーに送信するメモリ、時間、および帯域幅のコストを節約し、ユーザーを S3 ファイルの事前署名 URL に自動的にリダイレクトします。

ts
const response = new Response(s3file);
console.log(response);
txt
Response (0 KB) {
  ok: false,
  url: "",
  status: 302,
  statusText: "",
  headers: Headers {
    "location": "https://<account-id>.r2.cloudflarestorage.com/...",
  },
  redirected: true,
  bodyUsed: false
}

S3 互換サービスのサポート

Bun の S3 実装は、S3 互換のストレージサービスで動作します。適切なエンドポイントを指定するだけです:

AWS S3 で Bun の S3Client を使用

AWS S3 がデフォルトです。AWS S3 の場合、endpoint オプションの代わりに region オプションを渡すこともできます。

ts
import { S3Client } from "bun";

// AWS S3
const s3 = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // region: "us-east-1",
});

Google Cloud Storage で Bun の S3Client を使用

Google Cloud Storage で Bun の S3 クライアントを使用するには、S3Client コンストラクターで endpoint"https://storage.googleapis.com" に設定します。

ts
import { S3Client } from "bun";

// Google Cloud Storage
const gcs = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  endpoint: "https://storage.googleapis.com",
});

Cloudflare R2 で Bun の S3Client を使用

Cloudflare R2 で Bun の S3 クライアントを使用するには、S3Client コンストラクターで endpoint を R2 エンドポイントに設定します。R2 エンドポイントにはアカウント ID が含まれます。

ts
import { S3Client } from "bun";

// CloudFlare R2
const r2 = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  endpoint: "https://<account-id>.r2.cloudflarestorage.com",
});

DigitalOcean Spaces で Bun の S3Client を使用

DigitalOcean Spaces で Bun の S3 クライアントを使用するには、S3Client コンストラクターで endpoint を DigitalOcean Spaces エンドポイントに設定します。

ts
import { S3Client } from "bun";

const spaces = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  // region: "nyc3",
  endpoint: "https://<region>.digitaloceanspaces.com",
});

MinIO で Bun の S3Client を使用

MinIO で Bun の S3 クライアントを使用するには、S3Client コンストラクターで endpoint を MinIO が実行されている URL に設定します。

ts
import { S3Client } from "bun";

const minio = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",

  // 本番環境では正しいエンドポイント URL を使用してください
  // 本番環境では localhost ではない可能性があります
  endpoint: "http://localhost:9000",
});

supabase で Bun の S3Client を使用

supabase で Bun の S3 クライアントを使用するには、S3Client コンストラクターで endpoint を supabase エンドポイントに設定します。supabase エンドポイントにはアカウント ID と /storage/v1/s3 パスが含まれます。supabase ダッシュボードの https://supabase.com/dashboard/project/<account-id>/settings/storage で「S3 プロトコル経由の接続を有効にする」をオンにし、同じセクションでリージョンを設定してください。

ts
import { S3Client } from "bun";

const supabase = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  region: "us-west-1",
  endpoint: "https://<account-id>.supabase.co/storage/v1/s3/storage",
});

S3 仮想ホストスタイルエンドポイントでの Bun の S3Client の使用

S3 仮想ホストスタイルエンドポイントを使用する場合、virtualHostedStyle オプションを true に設定する必要があります。

NOTE

- エンドポイントを指定しない場合、Bun は提供されたリージョンとバケットを使用して AWS S3 エンドポイントを自動的に決定します。 - リージョンが指定されていない場合、Bun はデフォルトで us-east-1 を使用します。 - エンドポイントを明示的に指定する場合、バケット名を指定する必要はありません。
ts
import { S3Client } from "bun";

// リージョンとバケットから推測された AWS S3 エンドポイント
const s3 = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  virtualHostedStyle: true, 
  // endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com",
  // region: "us-east-1",
});

// AWS S3
const s3WithEndpoint = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  endpoint: "https://<bucket-name>.s3.<region>.amazonaws.com",
  virtualHostedStyle: true, 
});

// Cloudflare R2
const r2WithEndpoint = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  endpoint: "https://<bucket-name>.<account-id>.r2.cloudflarestorage.com",
  virtualHostedStyle: true, 
});

認証情報

認証情報は S3 使用の最も難しい部分の 1 つであり、できるだけ簡単にしようとしました。デフォルトでは、Bun は以下の認証情報の環境変数を読み取ります。

オプション名環境変数
accessKeyIdS3_ACCESS_KEY_ID
secretAccessKeyS3_SECRET_ACCESS_KEY
regionS3_REGION
endpointS3_ENDPOINT
bucketS3_BUCKET
sessionTokenS3_SESSION_TOKEN

S3_* 環境変数が設定されていない場合、Bun は上記の各オプションについて AWS_* 環境変数もチェックします。

オプション名フォールバック環境変数
accessKeyIdAWS_ACCESS_KEY_ID
secretAccessKeyAWS_SECRET_ACCESS_KEY
regionAWS_REGION
endpointAWS_ENDPOINT
bucketAWS_BUCKET
sessionTokenAWS_SESSION_TOKEN

これらの環境変数は、.env ファイル または初期化時のプロセス環境から読み取られます(これには process.env は使用されません)。

これらのデフォルトは、s3.file(credentials)new Bun.S3Client(credentials)、または認証情報を受け入れるメソッドに渡すオプションによって上書きされます。したがって、例えば、異なるバケットに同じ認証情報を使用する場合、.env ファイルで認証情報を 1 回設定し、すべての認証情報を再度指定せずに s3.file() 関数に bucket: "my-bucket" を渡すことができます。

S3Client オブジェクト

環境変数を使用しない場合、または複数のバケットを使用する場合、S3Client オブジェクトを作成して認証情報を明示的に設定できます。

ts
import { S3Client } from "bun";

const client = new S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // sessionToken: "..."
  endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
  // endpoint: "http://localhost:9000", // MinIO
});

// Response を使用して書き込み
await file.write(new Response("Hello World!"));

// URL を事前署名
const url = file.presign({
  expiresIn: 60 * 60 * 24, // 1 日
  acl: "public-read",
});

// ファイルを削除
await file.delete();

S3Client.prototype.write

S3 にファイルをアップロードまたは書き込むには、S3Client インスタンスで write を呼び出します。

ts
const client = new Bun.S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  endpoint: "https://s3.us-east-1.amazonaws.com",
  bucket: "my-bucket",
});

await client.write("my-file.txt", "Hello World!");
await client.write("my-file.txt", new Response("Hello World!"));

// 同等
// await client.file("my-file.txt").write("Hello World!");

S3Client.prototype.delete

S3 からファイルを削除するには、S3Client インスタンスで delete を呼び出します。

ts
const client = new Bun.S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
});

await client.delete("my-file.txt");
// 同等
// await client.file("my-file.txt").delete();

S3Client.prototype.exists

S3 にファイルが存在するか確認するには、S3Client インスタンスで exists を呼び出します。

ts
const client = new Bun.S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
});

const exists = await client.exists("my-file.txt");
// 同等
// const exists = await client.file("my-file.txt").exists();

S3File

S3File インスタンスは、S3Client インスタンスメソッドまたは s3.file() 関数を呼び出すことによって作成されます。Bun.file() と同様に、S3File インスタンスは遅延です。これらは作成時に必ずしも存在するものを参照するわけではありません。そのため、ネットワークリクエストを伴わないすべてのメソッドは完全に同期です。

ts
interface S3File extends Blob {
  slice(start: number, end?: number): S3File;
  exists(): Promise<boolean>;
  unlink(): Promise<void>;
  presign(options: S3Options): string;
  text(): Promise<string>;
  json(): Promise<any>;
  bytes(): Promise<Uint8Array>;
  arrayBuffer(): Promise<ArrayBuffer>;
  stream(options: S3Options): ReadableStream;
  write(
    data: string | Uint8Array | ArrayBuffer | Blob | ReadableStream | Response | Request,
    options?: BlobPropertyBag,
  ): Promise<number>;

  exists(options?: S3Options): Promise<boolean>;
  unlink(options?: S3Options): Promise<void>;
  delete(options?: S3Options): Promise<void>;
  presign(options?: S3Options): string;

  stat(options?: S3Options): Promise<S3Stat>;
  /**
   * サイズはネットワークリクエストが必要なため、同期では利用できません。
   *
   * @deprecated 代わりに `stat()` を使用してください。
   */
  size: NaN;

  // ... 簡潔にするため省略
}

Bun.file() と同様に、S3FileBlob を拡張するため、Blob で利用可能なすべてのメソッドは S3File でも利用可能です。ローカルファイルからデータを読み取るための同じ API は、S3 からデータを読み取るためにも利用可能です。

メソッド出力
await s3File.text()string
await s3File.bytes()Uint8Array
await s3File.json()JSON
await s3File.stream()ReadableStream
await s3File.arrayBuffer()ArrayBuffer

つまり、S3File インスタンスを fetch()Response、および Blob インスタンスを受け入れる他の Web API で使用できます。

slice による部分的な読み取り

ファイルの部分範囲を読み取るには、slice メソッドを使用できます。

ts
const partial = s3file.slice(0, 1024);

// 部分範囲を Uint8Array として読み取り
const bytes = await partial.bytes();

// 部分範囲を文字列として読み取り
const text = await partial.text();

内部的には、これは HTTP Range ヘッダーを使用して必要なバイトのみをリクエストすることで動作します。この slice メソッドは Blob.prototype.slice と同じです。

S3 からのファイル削除

S3 からファイルを削除するには、delete メソッドを使用できます。

ts
await s3file.delete();
// await s3File.unlink();

deleteunlink と同じです。

エラーコード

Bun の S3 API がエラーをスローする場合、以下の値のいずれかに一致する code プロパティがあります:

  • ERR_S3_MISSING_CREDENTIALS
  • ERR_S3_INVALID_METHOD
  • ERR_S3_INVALID_PATH
  • ERR_S3_INVALID_ENDPOINT
  • ERR_S3_INVALID_SIGNATURE
  • ERR_S3_INVALID_SESSION_TOKEN

S3 オブジェクトストレージサービスがエラーを返す場合(Bun ではない)、S3Error インスタンス(名前が "S3Error"Error インスタンス)になります。

S3Client 静的メソッド

S3Client クラスは S3 と対話するためのいくつかの静的メソッドを提供します。

S3Client.write(静的)

バケット内のパスに直接データを書き込むには、S3Client.write 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

// 文字列を書き込み
await S3Client.write("my-file.txt", "Hello World");

// タイプ付き JSON を書き込み
await S3Client.write("data.json", JSON.stringify({ hello: "world" }), {
  ...credentials,
  type: "application/json",
});

// fetch から書き込み
const res = await fetch("https://example.com/data");
await S3Client.write("data.bin", res, credentials);

// ACL 付きで書き込み
await S3Client.write("public.html", html, {
  ...credentials,
  acl: "public-read",
  type: "text/html",
});

これは new S3Client(credentials).write("my-file.txt", "Hello World") を呼び出すのと同等です。

S3Client.presign(静的)

S3 ファイルの事前署名 URL を生成するには、S3Client.presign 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

const url = S3Client.presign("my-file.txt", {
  ...credentials,
  expiresIn: 3600,
});

これは new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 }) を呼び出すのと同等です。

S3Client.list(静的)

バケット内の一部またはすべて(最大 1,000)のオブジェクトをリストするには、S3Client.list 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

// バケット内の(最大)1000 個のオブジェクトをリスト
const allObjects = await S3Client.list(null, credentials);

// `uploads/` プレフィックス以下の(最大)500 個のオブジェクトをリストし、各オブジェクトの所有者フィールドを含む
const uploads = await S3Client.list({
  prefix: 'uploads/',
  maxKeys: 500,
  fetchOwner: true,
}, credentials);

// より多くの結果が利用可能か確認
if (uploads.isTruncated) {
  // `uploads/` プレフィックス以下の次のバッチのオブジェクトをリスト
  const moreUploads = await S3Client.list({
    prefix: 'uploads/',
    maxKeys: 500,
    startAfter: uploads.contents!.at(-1).key
    fetchOwner: true,
  }, credentials);
}

これは new S3Client(credentials).list() を呼び出すのと同等です。

S3Client.exists(静的)

S3 ファイルが存在するか確認するには、S3Client.exists 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

const exists = await S3Client.exists("my-file.txt", credentials);

同じメソッドは S3File インスタンスでも動作します。

ts
import { s3 } from "bun";

const s3file = s3.file("my-file.txt", {
  // ...credentials,
});

const exists = await s3file.exists();

S3Client.size(静的)

S3 ファイルのサイズをダウンロードせずにすばやく確認するには、S3Client.size 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

const bytes = await S3Client.size("my-file.txt", credentials);

これは new S3Client(credentials).size("my-file.txt") を呼び出すのと同等です。

S3Client.stat(静的)

S3 ファイルのサイズ、etag、およびその他のメタデータを取得するには、S3Client.stat 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
  // endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};

const stat = await S3Client.stat("my-file.txt", credentials);
txt
{
  etag: "\"7a30b741503c0b461cc14157e2df4ad8\"",
  lastModified: 2025-01-07T00:19:10.000Z,
  size: 1024,
  type: "text/plain;charset=utf-8",
}

S3Client.delete(静的)

S3 ファイルを削除するには、S3Client.delete 静的メソッドを使用できます。

ts
import { S3Client } from "bun";

const credentials = {
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
  // endpoint: "https://s3.us-east-1.amazonaws.com",
};

await S3Client.delete("my-file.txt", credentials);
// 同等
// await new S3Client(credentials).delete("my-file.txt");

// S3Client.unlink は S3Client.delete のエイリアスです
await S3Client.unlink("my-file.txt", credentials);

s3:// プロトコル

ローカルファイルと S3 ファイルに同じコードをより簡単に使用できるように、s3:// プロトコルは fetch および Bun.file() でサポートされています。

ts
const response = await fetch("s3://my-bucket/my-file.txt");
const file = Bun.file("s3://my-bucket/my-file.txt");

さらに、fetch および Bun.file 関数に s3 オプションを渡すことができます。

ts
const response = await fetch("s3://my-bucket/my-file.txt", {
  s3: {
    accessKeyId: "your-access-key",
    secretAccessKey: "your-secret-key",
    endpoint: "https://s3.us-east-1.amazonaws.com",
  },
  headers: {
    range: "bytes=0-1023",
  },
});

UTF-8、UTF-16、および BOM(バイトオーダーマーク)

Response および Blob と同様に、S3File はデフォルトで UTF-8 エンコーディングを想定します。

S3Filetext() または json() メソッドの 1 つを呼び出す場合:

  • UTF-16 バイトオーダーマーク(BOM)が検出された場合、UTF-16 として処理されます。JavaScriptCore は UTF-16 をネイティブにサポートしているため、UTF-8 トランスコードプロセスをスキップします(BOM を削除します)。これは主に良いことですが、UTF-16 文字列に無効なサロゲートペア文字がある場合、それらは JavaScriptCore に渡されます(ソースコードと同じ)。
  • UTF-8 BOM が検出された場合、文字列が JavaScriptCore に渡される前に削除され、無効な UTF-8 コードポイントは Unicode 置換文字(\uFFFD)に置き換えられます。
  • UTF-32 はサポートされていません。

Bun by www.bunjs.com.cn 編集