Skip to content

Produktionsserver lesen, laden und schreiben Dateien oft in S3-kompatible Objektspeicherdienste statt in das lokale Dateisystem. Historisch gesehen bedeutet das, dass lokale Dateisystem-APIs, die Sie in der Entwicklung verwenden, in der Produktion nicht verwendet werden können. Wenn Sie Bun verwenden, ist das anders.

Buns S3-API ist schnell

Bun bietet schnelle, native Bindungen für die Interaktion mit S3-kompatiblen Objektspeicherdiensten. Buns S3-API ist einfach gestaltet und fühlt sich ähnlich an wie die Response- und Blob-APIs von fetch (wie Buns lokale Dateisystem-APIs).

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

// Bun.s3 liest Umgebungsvariablen für Anmeldeinformationen
// file() gibt eine verzögerte Referenz auf eine Datei in S3 zurück
const metadata = s3.file("123.json");

// Von S3 als JSON herunterladen
const data = await metadata.json();

// Nach S3 hochladen
await write(metadata, JSON.stringify({ name: "John", age: 30 }));

// Eine URL vorab signieren (synchron - keine Netzwerkanfrage erforderlich)
const url = metadata.presign({
  acl: "public-read",
  expiresIn: 60 * 60 * 24, // 1 Tag
});

// Die Datei löschen
await metadata.delete();

S3 ist der De-facto-Standard für Internet-Dateisysteme. Buns S3-API funktioniert mit S3-kompatiblen Speicherdiensten wie:

  • AWS S3
  • Cloudflare R2
  • DigitalOcean Spaces
  • MinIO
  • Backblaze B2
  • ...und jedem anderen S3-kompatiblen Speicherdienst

Grundlegende Verwendung

Es gibt mehrere Möglichkeiten, mit Buns S3-API zu interagieren.

Bun.S3Client & Bun.s3

Bun.s3 entspricht new Bun.S3Client() und verwendet Umgebungsvariablen für Anmeldeinformationen.

Um Anmeldeinformationen explizit festzulegen, übergeben Sie sie an den Bun.S3Client-Konstruktor.

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 ist ein globaler Singleton, der `new Bun.S3Client()` entspricht

Arbeiten mit S3-Dateien

Die file-Methode in S3Client gibt eine verzögerte Referenz auf eine Datei in S3 zurück.

ts
// Eine verzögerte Referenz auf eine Datei in S3
const s3file: S3File = client.file("123.json");

Wie Bun.file(path) ist die file-Methode von S3Client synchron. Sie führt keine Netzwerkanfragen durch, bis Sie eine Methode aufrufen, die von einer Netzwerkanfrage abhängt.

Dateien von S3 lesen

Wenn Sie die fetch-API verwendet haben, sind Sie mit den Response- und Blob-APIs vertraut. S3File erweitert Blob. Die gleichen Methoden, die für Blob funktionieren, funktionieren auch für S3File.

ts
// Eine S3File als Text lesen
const text = await s3file.text();

// Eine S3File als JSON lesen
const json = await s3file.json();

// Eine S3File als ArrayBuffer lesen
const buffer = await s3file.arrayBuffer();

// Nur die ersten 1024 Bytes abrufen
const partial = await s3file.slice(0, 1024).text();

// Die Datei streamen
const stream = s3file.stream();
for await (const chunk of stream) {
  console.log(chunk);
}

Speicheroptimierung

Methoden wie text(), json(), bytes() oder arrayBuffer() vermeiden es, den String oder Bytes im Speicher zu duplizieren, wenn möglich.

Wenn der Text zufällig ASCII ist, überträgt Bun den String direkt an JavaScriptCore (die Engine) ohne Transkodierung und ohne den String im Speicher zu duplizieren. Wenn Sie .bytes() oder .arrayBuffer() verwenden, wird auch das Duplizieren der Bytes im Speicher vermieden.

Diese Hilfsmethoden vereinfachen nicht nur die API, sie machen sie auch schneller.

Schreiben & Hochladen von Dateien nach S3

Das Schreiben nach S3 ist genauso einfach.

ts
// Einen String schreiben (ersetzt die Datei)
await s3file.write("Hallo Welt!");

// Einen Buffer schreiben (ersetzt die Datei)
await s3file.write(Buffer.from("Hallo Welt!"));

// Eine Response schreiben (ersetzt die Datei)
await s3file.write(new Response("Hallo Welt!"));

// Mit Inhaltstyp schreiben
await s3file.write(JSON.stringify({ name: "John", age: 30 }), {
  type: "application/json",
});

// Mit einem Writer schreiben (Streaming)
const writer = s3file.writer({ type: "application/json" });
writer.write("Hallo");
writer.write(" Welt!");
await writer.end();

// Mit Bun.write schreiben
await Bun.write(s3file, "Hallo Welt!");

Arbeiten mit großen Dateien (Streams)

Bun verarbeitet automatisch Multi-Part-Uploads für große Dateien und bietet Streaming-Funktionen. Die gleiche API, die für lokale Dateien funktioniert, funktioniert auch für S3-Dateien.

ts
// Eine große Datei schreiben
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
const writer = s3file.writer({
  // Bei Netzwerkfehlern automatisch bis zu 3 Mal wiederholen
  retry: 3,

  // Bis zu 10 Anfragen gleichzeitig in die Warteschlange stellen
  queueSize: 10,

  // In 5 MB-Chunks hochladen
  partSize: 5 * 1024 * 1024,
});
for (let i = 0; i < 10; i++) {
  writer.write(bigFile);
  await writer.flush();
}
await writer.end();

Vorab signierte URLs

Wenn Ihr Produktionsdienst Benutzern das Hochladen von Dateien auf Ihren Server ermöglichen muss, ist es oft zuverlässiger, wenn der Benutzer direkt nach S3 hochlädt, anstatt dass Ihr Server als Vermittler fungiert.

Um dies zu ermöglichen, können Sie URLs für S3-Dateien vorab signieren. Dies generiert eine URL mit einer Signatur, die es einem Benutzer ermöglicht, diese spezifische Datei sicher nach S3 hochzuladen, ohne Ihre Anmeldeinformationen preiszugeben oder ihnen unnötigen Zugriff auf Ihren Bucket zu gewähren.

Das Standardverhalten ist das Generieren einer GET-URL, die in 24 Stunden abläuft. Bun versucht, den Inhaltstyp aus der Dateierweiterung abzuleiten. Wenn keine Ableitung möglich ist, wird standardmäßig application/octet-stream verwendet.

ts
import { s3 } from "bun";

// Eine vorab signierte URL generieren, die in 24 Stunden abläuft (Standard)
const download = s3.presign("my-file.txt"); // GET, text/plain, läuft in 24 Stunden ab

const upload = s3.presign("my-file", {
  expiresIn: 3600, // 1 Stunde
  method: "PUT",
  type: "application/json", // Keine Erweiterung zum Ableiten, also können wir den Inhaltstyp als JSON angeben
});

// Sie können .presign() aufrufen, wenn Sie eine Dateireferenz haben, aber vermeiden Sie dies
// es sei denn, Sie haben bereits eine Referenz (um Speichernutzung zu vermeiden).
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
  expiresIn: 3600, // 1 Stunde
});

ACLs festlegen

Um eine ACL (Access Control List) auf einer vorab signierten URL festzulegen, übergeben Sie die acl-Option:

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

Sie können eine der folgenden ACLs verwenden:

ACLErklärung
"public-read"Das Objekt ist für die Öffentlichkeit lesbar.
"private"Das Objekt ist nur für den Bucket-Besitzer lesbar.
"public-read-write"Das Objekt ist für die Öffentlichkeit lesbar und beschreibbar.
"authenticated-read"Das Objekt ist für den Bucket-Besitzer und authentifizierte Benutzer lesbar.
"aws-exec-read"Das Objekt ist für das AWS-Konto lesbar, das die Anfrage gestellt hat.
"bucket-owner-read"Das Objekt ist für den Bucket-Besitzer lesbar.
"bucket-owner-full-control"Das Objekt ist für den Bucket-Besitzer lesbar und beschreibbar.
"log-delivery-write"Das Objekt ist für AWS-Dienste beschreibbar, die für die Protokollbereitstellung verwendet werden.

Ablaufende URLs

Um eine Ablaufzeit für eine vorab signierte URL festzulegen, übergeben Sie die expiresIn-Option.

ts
const url = s3file.presign({
  // Sekunden
  expiresIn: 3600, // 1 Stunde

  // Access Control List
  acl: "public-read",

  // HTTP-Methode
  method: "PUT",
});

method

Um die HTTP-Methode für eine vorab signierte URL festzulegen, übergeben Sie die method-Option.

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

new Response(S3File)

Um Benutzer schnell zu einer vorab signierten URL für eine S3-Datei umzuleiten, übergeben Sie eine S3File-Instanz als Body an ein Response-Objekt.

Dies leitet den Benutzer automatisch zur vorab signierten URL für die S3-Datei um und spart Ihnen die Speicher-, Zeit- und Bandbreitenkosten für das Herunterladen der Datei auf Ihren Server und das Zurücksenden an den Benutzer.

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
}

Unterstützung für S3-kompatible Dienste

Buns S3-Implementierung funktioniert mit jedem S3-kompatiblen Speicherdienst. Geben Sie einfach den entsprechenden Endpunkt an:

Verwendung von Buns S3Client mit AWS S3

AWS S3 ist der Standard. Sie können auch eine region-Option anstelle einer endpoint-Option für AWS S3 übergeben.

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",
});

Verwendung von Buns S3Client mit Google Cloud Storage

Um Buns S3-Client mit Google Cloud Storage zu verwenden, setzen Sie endpoint auf "https://storage.googleapis.com" im S3Client-Konstruktor.

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",
});

Verwendung von Buns S3Client mit Cloudflare R2

Um Buns S3-Client mit Cloudflare R2 zu verwenden, setzen Sie endpoint auf den R2-Endpunkt im S3Client-Konstruktor. Der R2-Endpunkt enthält Ihre Konto-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",
});

Verwendung von Buns S3Client mit DigitalOcean Spaces

Um Buns S3-Client mit DigitalOcean Spaces zu verwenden, setzen Sie endpoint auf den DigitalOcean Spaces-Endpunkt im S3Client-Konstruktor.

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",
});

Verwendung von Buns S3Client mit MinIO

Um Buns S3-Client mit MinIO zu verwenden, setzen Sie endpoint auf die URL, auf der MinIO läuft, im S3Client-Konstruktor.

ts
import { S3Client } from "bun";

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

  // Stellen Sie sicher, dass die korrekte Endpunkt-URL verwendet wird
  // In der Produktion ist es möglicherweise nicht localhost!
  endpoint: "http://localhost:9000",
});

Verwendung von Buns S3Client mit supabase

Um Buns S3-Client mit supabase zu verwenden, setzen Sie endpoint auf den supabase-Endpunkt im S3Client-Konstruktor. Der supabase-Endpunkt enthält Ihre Konto-ID und den Pfad /storage/v1/s3. Stellen Sie sicher, dass Sie "Enable connection via S3 protocol" im supabase-Dashboard unter https://supabase.com/dashboard/project/<account-id>/settings/storage aktivieren und die Region im gleichen Abschnitt angeben.

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",
});

Verwendung von Buns S3Client mit S3 Virtual Hosted-Style-Endpunkten

Bei Verwendung eines S3 Virtual Hosted-Style-Endpunkts müssen Sie die virtualHostedStyle-Option auf true setzen.

NOTE

- Wenn Sie keinen Endpunkt angeben, bestimmt Bun automatisch den AWS S3-Endpunkt anhand der angegebenen Region und des Buckets. - Wenn keine Region angegeben ist, verwendet Bun standardmäßig us-east-1. - Wenn Sie explizit einen Endpunkt angeben, müssen Sie keinen Bucket-Namen angeben.
ts
import { S3Client } from "bun";

// AWS S3-Endpunkt abgeleitet von Region und Bucket
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, 
});

Anmeldeinformationen

Anmeldeinformationen sind einer der schwierigsten Teile bei der Verwendung von S3, und wir haben versucht, es so einfach wie möglich zu machen. Standardmäßig liest Bun die folgenden Umgebungsvariablen für Anmeldeinformationen.

OptionsnameUmgebungsvariable
accessKeyIdS3_ACCESS_KEY_ID
secretAccessKeyS3_SECRET_ACCESS_KEY
regionS3_REGION
endpointS3_ENDPOINT
bucketS3_BUCKET
sessionTokenS3_SESSION_TOKEN

Wenn die S3_*-Umgebungsvariable nicht gesetzt ist, überprüft Bun auch die AWS_*-Umgebungsvariable für jede der oben genannten Optionen.

OptionsnameFallback-Umgebungsvariable
accessKeyIdAWS_ACCESS_KEY_ID
secretAccessKeyAWS_SECRET_ACCESS_KEY
regionAWS_REGION
endpointAWS_ENDPOINT
bucketAWS_BUCKET
sessionTokenAWS_SESSION_TOKEN

Diese Umgebungsvariablen werden aus .env-Dateien oder aus der Prozessumgebung zum Initialisierungszeitpunkt gelesen (process.env wird hierfür nicht verwendet).

Diese Standardwerte werden durch die Optionen überschrieben, die Sie an s3.file(credentials), new Bun.S3Client(credentials) oder eine der Methoden übergeben, die Anmeldeinformationen akzeptieren. Wenn Sie also beispielsweise die gleichen Anmeldeinformationen für verschiedene Buckets verwenden, können Sie die Anmeldeinformationen einmal in Ihrer .env-Datei festlegen und dann bucket: "my-bucket" an die s3.file()-Funktion übergeben, ohne alle Anmeldeinformationen erneut angeben zu müssen.

S3Client-Objekte

Wenn Sie keine Umgebungsvariablen verwenden oder mehrere Buckets verwenden, können Sie ein S3Client-Objekt erstellen, um Anmeldeinformationen explizit festzulegen.

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
});

// Mit einer Response schreiben
await file.write(new Response("Hallo Welt!"));

// Eine URL vorab signieren
const url = file.presign({
  expiresIn: 60 * 60 * 24, // 1 Tag
  acl: "public-read",
});

// Die Datei löschen
await file.delete();

S3Client.prototype.write

Um eine Datei nach S3 hochzuladen oder zu schreiben, rufen Sie write auf der S3Client-Instanz auf.

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", "Hallo Welt!");
await client.write("my-file.txt", new Response("Hallo Welt!"));

// entspricht
// await client.file("my-file.txt").write("Hallo Welt!");

S3Client.prototype.delete

Um eine Datei aus S3 zu löschen, rufen Sie delete auf der S3Client-Instanz auf.

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

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

S3Client.prototype.exists

Um zu überprüfen, ob eine Datei in S3 existiert, rufen Sie exists auf der S3Client-Instanz auf.

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");
// entspricht
// const exists = await client.file("my-file.txt").exists();

S3File

S3File-Instanzen werden durch Aufruf der S3Client-Instanzmethode oder der s3.file()-Funktion erstellt. Wie Bun.file() sind S3File-Instanzen verzögert (lazy). Sie beziehen sich nicht auf etwas, das zum Zeitpunkt der Erstellung notwendigerweise existiert. Deshalb sind alle Methoden, die keine Netzwerkanfragen beinhalten, vollständig synchron.

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>;
  /**
   * Größe ist nicht synchron verfügbar, da sie eine Netzwerkanfrage erfordert.
   *
   * @deprecated Verwenden Sie stat() stattdessen.
   */
  size: NaN;

  // ... mehr der Kürze halber weggelassen
}

Wie Bun.file() erweitert S3File Blob, sodass alle Methoden, die für Blob verfügbar sind, auch für S3File verfügbar sind. Die gleiche API zum Lesen von Daten aus einer lokalen Datei ist auch zum Lesen von Daten aus S3 verfügbar.

MethodeAusgabe
await s3File.text()string
await s3File.bytes()Uint8Array
await s3File.json()JSON
await s3File.stream()ReadableStream
await s3File.arrayBuffer()ArrayBuffer

Das bedeutet, dass die Verwendung von S3File-Instanzen mit fetch(), Response und anderen Web-APIs, die Blob-Instanzen akzeptieren, einfach funktioniert.

Teilweises Lesen mit slice

Um einen teilweisen Bereich einer Datei zu lesen, können Sie die slice-Methode verwenden.

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

// Den teilweisen Bereich als Uint8Array lesen
const bytes = await partial.bytes();

// Den teilweisen Bereich als String lesen
const text = await partial.text();

Intern funktioniert dies durch Verwendung des HTTP Range-Headers, um nur die gewünschten Bytes anzufordern. Diese slice-Methode ist die gleiche wie Blob.prototype.slice.

Löschen von Dateien aus S3

Um eine Datei aus S3 zu löschen, können Sie die delete-Methode verwenden.

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

delete ist das gleiche wie unlink.

Fehlercodes

Wenn Buns S3-API einen Fehler wirft, hat dieser eine code-Eigenschaft, die einem der folgenden Werte entspricht:

  • 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

Wenn der S3 Object Storage-Dienst einen Fehler zurückgibt (das heißt, nicht Bun), ist es eine S3Error-Instanz (eine Error-Instanz mit dem Namen "S3Error").

S3Client-statische Methoden

Die S3Client-Klasse bietet mehrere statische Methoden für die Interaktion mit S3.

S3Client.write (statisch)

Um Daten direkt in einen Pfad im Bucket zu schreiben, können Sie die statische Methode S3Client.write verwenden.

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
};

// String schreiben
await S3Client.write("my-file.txt", "Hallo Welt");

// JSON mit Typ schreiben
await S3Client.write("data.json", JSON.stringify({ hello: "world" }), {
  ...credentials,
  type: "application/json",
});

// Von fetch schreiben
const res = await fetch("https://example.com/data");
await S3Client.write("data.bin", res, credentials);

// Mit ACL schreiben
await S3Client.write("public.html", html, {
  ...credentials,
  acl: "public-read",
  type: "text/html",
});

Dies entspricht dem Aufruf von new S3Client(credentials).write("my-file.txt", "Hallo Welt").

S3Client.presign (statisch)

Um eine vorab signierte URL für eine S3-Datei zu generieren, können Sie die statische Methode S3Client.presign verwenden.

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,
});

Dies entspricht dem Aufruf von new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 }).

S3Client.list (statisch)

Um einige oder alle (bis zu 1.000) Objekte in einem Bucket aufzulisten, können Sie die statische Methode S3Client.list verwenden.

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
};

// Bis zu 1000 Objekte im Bucket auflisten
const allObjects = await S3Client.list(null, credentials);

// Bis zu 500 Objekte unter dem `uploads/`-Präfix auflisten, mit Besitzerfeld für jedes Objekt
const uploads = await S3Client.list({
  prefix: 'uploads/',
  maxKeys: 500,
  fetchOwner: true,
}, credentials);

// Überprüfen, ob weitere Ergebnisse verfügbar sind
if (uploads.isTruncated) {
  // Nächste Charge von Objekten unter dem `uploads/`-Präfix auflisten
  const moreUploads = await S3Client.list({
    prefix: 'uploads/',
    maxKeys: 500,
    startAfter: uploads.contents!.at(-1).key
    fetchOwner: true,
  }, credentials);
}

Dies entspricht dem Aufruf von new S3Client(credentials).list().

S3Client.exists (statisch)

Um zu überprüfen, ob eine S3-Datei existiert, können Sie die statische Methode S3Client.exists verwenden.

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);

Die gleiche Methode funktioniert auch bei S3File-Instanzen.

ts
import { s3 } from "bun";

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

const exists = await s3file.exists();

S3Client.size (statisch)

Um schnell die Größe einer S3-Datei zu überprüfen, ohne sie herunterzuladen, können Sie die statische Methode S3Client.size verwenden.

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);

Dies entspricht dem Aufruf von new S3Client(credentials).size("my-file.txt").

S3Client.stat (statisch)

Um die Größe, den ETag und andere Metadaten einer S3-Datei zu erhalten, können Sie die statische Methode S3Client.stat verwenden.

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 (statisch)

Um eine S3-Datei zu löschen, können Sie die statische Methode S3Client.delete verwenden.

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);
// entspricht
// await new S3Client(credentials).delete("my-file.txt");

// S3Client.unlink ist ein Alias für S3Client.delete
await S3Client.unlink("my-file.txt", credentials);

s3://-Protokoll

Um die Verwendung des gleichen Codes für lokale Dateien und S3-Dateien zu erleichtern, wird das s3://-Protokoll in fetch und Bun.file() unterstützt.

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

Sie können zusätzlich s3-Optionen an die fetch- und Bun.file-Funktionen übergeben.

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 und BOM (Byte Order Mark)

Wie Response und Blob geht S3File standardmäßig von UTF-8-Kodierung aus.

Beim Aufruf einer der text()- oder json()-Methoden auf einer S3File:

  • Wenn eine UTF-16-Byte-Reihenfolge-Markierung (BOM) erkannt wird, wird sie als UTF-16 behandelt. JavaScriptCore unterstützt nativ UTF-16, sodass es den UTF-8-Transkodierungsprozess überspringt (und das BOM entfernt). Das ist meist gut, bedeutet aber, dass ungültige Surrogatpaar-Zeichen in Ihrem UTF-16-String an JavaScriptCore weitergegeben werden (genau wie im Quellcode).
  • Wenn ein UTF-8-BOM erkannt wird, wird es entfernt, bevor der String an JavaScriptCore übergeben wird, und ungültige UTF-8-Codepoints werden durch das Unicode-Ersatzzeichen (\uFFFD) ersetzt.
  • UTF-32 wird nicht unterstützt.

Bun von www.bunjs.com.cn bearbeitet