Speicher & Dateien
Überblick
Abschnitt betitelt „Überblick“Das Modul client.storage bietet Methoden zur Dateiverwaltung — Hochladen, Herunterladen, Auflisten und Löschen. Es funktioniert je nach Serverkonfiguration sowohl mit lokalem Speicher als auch mit S3-kompatiblen Speicher-Backends.
Alle Speichermethoden verwenden den gemeinsamen Transport, sodass Authentifizierungstokens automatisch eingefügt werden.
Eine Datei hochladen
Abschnitt betitelt „Eine Datei hochladen“Verwenden Sie putObject(), um eine Datei hochzuladen. Es akzeptiert ein File- oder Blob-Objekt zusammen mit einem optionalen Speicherschlüssel und Metadaten:
const result = await client.storage.putObject({ file: fileObject, // File or Blob key: "products/images/camera.jpg", // Storage path (optional) bucket: "uploads", // Bucket name (optional) public: false, // Store public (permanent token-less URL) — optional, default false metadata: { // Custom metadata (optional) description: "Product photo", uploadedBy: "user-123" }});
// result: { key: string; bucket: string; storageUrl: string }Eine Datei über 8 MiB wird über den fortsetzbaren (TUS-)
Endpunkt des Servers hochgeladen, 8 MiB pro Anfrage, statt als eine Multipart-Anfrage, die der Server
vollständig parst — ein großer Upload kostet den Server so einen Chunk an Arbeitsspeicher, nicht das Drei-
bis Fünffache der Datei. Ein Chunk, der unterwegs scheitert, wird ab dem Punkt erneut gesendet, bis zu dem
der Server gekommen ist. Das Ergebnis, das gespeicherte Objekt und die Prüfungen des Servers sind
in beiden Fällen dieselben. Kann der fortsetzbare Endpunkt die Datei nicht annehmen (ein älterer
Server oder mehrere Instanzen, die Uploads nicht teilen), geht sie als ein
POST /api/storage/upload, ebenso jede spätere Datei desselben Clients. Siehe
Fortsetzbare Uploads (TUS).
Aus einem Datei-Input
Abschnitt betitelt „Aus einem Datei-Input“const input = document.querySelector<HTMLInputElement>("#file-input");const file = input?.files?.[0];
if (file) { const result = await client.storage.putObject({ file, key: `avatars/${userId}/${file.name}` }); console.log("Uploaded to:", result.key);}Eine signierte URL abrufen
Abschnitt betitelt „Eine signierte URL abrufen“Rufen Sie eine Download-URL und Metadaten für eine gespeicherte Datei ab:
const { url, metadata, fileNotFound } = await client.storage.getSignedUrl( "products/images/camera.jpg");
if (url) { console.log("Download URL:", url); console.log("Content type:", metadata?.contentType);} else { console.log("File not found");}Mit einem bestimmten Bucket:
const { url } = await client.storage.getSignedUrl( "camera.jpg", "product-images" // bucket);Das SDK speichert signierte URLs im Cache, um redundante Serveraufrufe zu vermeiden, bis das
Download-Token der jeweiligen URL abläuft. Gemeinsam gestellte
Abfragen — eine Seite mit Vorschauen, die getSignedUrl() im selben Tick aufruft — gehen als ein
POST /api/storage/metadata pro 100 Dateien an den Server, den der Rate Limiter als ein Zehntel der
ersetzten Anfragen zählt; eine Datei, die ein Aufrufer nicht lesen darf, lässt nur diesen einen Aufruf
fehlschlagen. Der Cache gehört zu den Zugangsdaten, die ihn befüllt
haben: Ändert sich das Access-Token — bei einer Abmeldung, wenn sich ein anderer Benutzer anmeldet
oder bei einer Aktualisierung —, beginnt er von vorn, sodass nie ein Benutzer eine URL erhält, die
für einen anderen erzeugt wurde.
Private vs. öffentliche URLs
Abschnitt betitelt „Private vs. öffentliche URLs“- Private Dateien erhalten eine URL mit einem kurzlebigen, pfadbeschränkten Download-Token (
?token=…, 5 Minuten, sofern der Server nichtSTORAGE_DOWNLOAD_TOKEN_TTLsetzt, was 0.23 nicht liest) — niemals Ihr Access-Token. Da es abläuft, speichern Sie keine private URL; speichern Sie den Pfad der Datei und rufen SiegetSignedUrl()beim Rendern erneut auf. - Öffentliche Dateien (unter dem Präfix
public/gespeichert — setzen Siestorage: { public: true }auf die Property oder übergeben Siepublic: trueanputObject) erhalten eine stabile, tokenlose, dauerhafte, CDN-cachefähige URL ohne Server-Roundtrip. Diese können sicher in einer Datenbank gespeichert und direkt verlinkt werden.
Dateien innerhalb von Text
Abschnitt betitelt „Dateien innerhalb von Text“Text, der eine Datei einbettet — die Bilder in einem Markdown-Feld — kann ebenfalls keine
private URL halten, sondern hält stattdessen eine Storage-Referenz:
rebase-storage:posts/cover.png, mit ?storageId=media, wenn die Datei in einer benannten
Quelle liegt. Das ist es, was der Markdown-Editor des Admin-Panels für ein hochgeladenes Bild
schreibt. Tauschen Sie die Referenzen beim Rendern des Texts gegen URLs aus:
import { resolveStorageReferences } from "@rebasepro/client";
const post = await client.data.collection("posts").findById("post-1");const body = await resolveStorageReferences(String(post?.body ?? ""), client);// `body` is the same markdown, each reference replaced by a fresh URL.Jedes Objekt wird einmal pro Aufruf signiert, aus seiner eigenen Quelle, sodass ein privates
Bild funktionsfähig bleibt, egal wie lange es schon hochgeladen ist. Eine Referenz, die ein
nicht mehr existierendes Objekt benennt, bleibt unverändert. storageReference(key, storageId?) erstellt eine solche Referenz, für Text, den Sie selbst schreiben.
Text, der gespeichert wurde, bevor es Referenzen gab, enthält die Download-URL einer privaten Datei
selbst, …/storage/file/posts/cover.png?token=…, deren Token wenige Minuten
nach dem Schreiben ablief. resolveStorageReferences erneuert auch diese:
Das Token nennt weiterhin das Objekt, sodass die URL durch eine frische ersetzt wird. Um
stattdessen Referenzen zu speichern, schreiben Sie den Text einmal mit
storageReferencesForDownloadUrls(text) um, was jede andere URL
unverändert lässt.
Eine Datei herunterladen
Abschnitt betitelt „Eine Datei herunterladen“Rufen Sie eine Datei als File-Objekt ab:
const file = await client.storage.getObject("products/images/camera.jpg");
if (file) { console.log("File name:", file.name); console.log("File type:", file.type); console.log("File size:", file.size);
// Create a download link const url = URL.createObjectURL(file); window.open(url);} else { console.log("File not found");}Mit einem bestimmten Bucket:
const file = await client.storage.getObject("camera.jpg", "product-images");Eine Datei löschen
Abschnitt betitelt „Eine Datei löschen“await client.storage.deleteObject("products/images/camera.jpg");
// With bucketawait client.storage.deleteObject("camera.jpg", "product-images");Das Löschen einer nicht vorhandenen Datei wirft keinen Fehler.
Dateien auflisten
Abschnitt betitelt „Dateien auflisten“Listen Sie Dateien nach Präfix auf, mit optionaler Paginierung:
const result = await client.storage.listObjects("products/images/", { bucket: "uploads", maxResults: 50, pageToken: undefined // for pagination});
for (const item of result.items) { console.log(item.fullPath, item.name, item.size, item.updated, item.contentType);}
// Paginateif (result.nextPageToken) { const nextPage = await client.storage.listObjects("products/images/", { pageToken: result.nextPageToken });}Jeder Eintrag trägt seine size in Bytes und updated (einen ISO-8601-
Zeitstempel) bei lokalem Speicher, S3 und GCS und seinen contentType bei lokalem Speicher
und GCS — genug, um einen Ordner ohne ein getSignedUrl() pro Datei anzuzeigen. Eine S3-
Auflistung hat keinen Content-Type; Ordner (result.prefixes) tragen keines der
drei.
Formate von Speicherschlüsseln
Abschnitt betitelt „Formate von Speicherschlüsseln“Das SDK verarbeitet Präfixe von Speicherschlüsseln transparent. Sie können Schlüssel mit oder ohne Protokollpräfix übergeben:
// All equivalent — the SDK strips the prefix internallyawait client.storage.getSignedUrl("local://products/image.jpg");await client.storage.getSignedUrl("s3://products/image.jpg");await client.storage.getSignedUrl("products/image.jpg");API-Referenz
Abschnitt betitelt „API-Referenz“| Methode | Beschreibung | Rückgabe |
|---|---|---|
putObject({ file, key?, bucket?, metadata? }) |
Eine Datei hochladen | UploadFileResult |
getSignedUrl(key, bucket?) |
Download-URL + Metadaten abrufen | DownloadConfig |
getObject(key, bucket?) |
Als File-Objekt herunterladen |
File | null |
deleteObject(key, bucket?) |
Eine Datei löschen | void |
listObjects(prefix, options?) |
Dateien nach Präfix auflisten | StorageListResult |
Nächste Schritte
Abschnitt betitelt „Nächste Schritte“- Speicherkonfiguration — S3 oder lokalen Speicher auf dem Server konfigurieren
- Daten abfragen — CRUD-Operationen und Query-Builder
- Authentifizierung — Anmeldung und Sitzungsverwaltung