Cloud-Speicher

Zugriff auf S3-kompatiblen Objektspeicher. Objekte hochladen, herunterladen, auflisten und verwalten, URLs für Download, Upload und Multipart-Teile vorsignieren sowie Objekte mit wahlfreiem Zugriff lesen.

Diese Seite ist eine API-Referenz. Ihre Ausschnitte setzen einen konfigurierten Speichereintrag, Zugriff auf jedes von ihnen genannte Dateisystem-Volume und die unten aufgeführten Berechtigungen voraus. Die Blöcke zu mehrteiligen Uploads und vorsignierten URLs sind Teilrezepte für die Client-Integration; die Anwendung muss die HTTP-Übertragungen ausführen und die zurückgegebenen ETags bereitstellen. Wenn sowohl eine Operation als auch die Ressourcenbereinigung fehlschlagen können, stellt die umgebende Anwendung report_cleanup_error(err) bereit. Die Funktion zeichnet den Bereinigungsfehler auf, ohne den ursprünglichen Fehler zu ersetzen.

Informationen zur Speicherkonfiguration finden Sie unter Cloud-Speicher.

Laden

local cloudstorage = require("cloudstorage")

Speicher abrufen

Rufen Sie eine Cloud-Speicherressource anhand ihrer Registry-ID ab:

local storage, err = cloudstorage.get("app.infra:files")
if err then
    return nil, err
end

local uploaded, upload_err = storage:upload_object("data/file.txt", "content")
storage:release()
if upload_err then return nil, upload_err end
return uploaded
Parameter Typ Beschreibung
id string Speicherressourcen-ID

Gibt zurück: Storage, error

Objekte hochladen

Inhalt aus String oder Datei hochladen:

local json = require("json")

local storage, storage_err = cloudstorage.get("app.infra:files")
if storage_err then return nil, storage_err end

-- Upload string content
local body, encode_err = json.encode({
    date = "2024-01-15",
    total = 1234
})
if encode_err then
    storage:release()
    return nil, encode_err
end
local ok, err = storage:upload_object("reports/daily.json", body)
if err then
    storage:release()
    return nil, err
end

-- Upload from file
local fs = require("fs")
local vol, fs_err = fs.get("app:data")
if fs_err then
    storage:release()
    return nil, fs_err
end
local file, open_err = vol:open("/large-file.bin", "r")
if open_err then
    storage:release()
    return nil, open_err
end

local uploaded, file_upload_err = storage:upload_object("backups/large-file.bin", file)
local _, close_err = file:close()

storage:release()
if file_upload_err then
    if close_err then report_cleanup_error(close_err) end
    return nil, file_upload_err
end
if close_err then return nil, close_err end
return uploaded
Parameter Typ Beschreibung
key string Objektschlüssel/Pfad
content string oder Reader Inhalt als String oder Datei-Reader
options table Optionale Metadaten und Optionen für bedingtes Schreiben

Gibt zurück: boolean, error

Upload-Optionen

Hängen Sie Metadaten an oder schützen Sie das Schreiben mit einer Optionstabelle:

local uploaded, err = storage:upload_object("reports/daily.json", body, {
    content_type = "application/json",
    cache_control = "max-age=3600",
    metadata = { owner = "team-a", run_id = "1234" },  -- stored as x-amz-meta-*
    only_if_absent = true                              -- fail if the key already exists
})
if err then return nil, err end
return uploaded
Option Typ Beschreibung
content_type string MIME-Typ
cache_control string Cache-Control-Header
content_disposition string Content-Disposition-Header
content_encoding string Content-Encoding-Header
metadata table Benutzer-Metadaten (string-Schlüssel/-Werte), gespeichert als x-amz-meta-*
headers table Zusätzliche Request-Header (string-Schlüssel/-Werte)
if_match string Nur schreiben, wenn das aktuelle Objekt-ETag übereinstimmt
if_none_match string Nur schreiben, wenn kein Objekt mit dem ETag übereinstimmt ("*" bedeutet beliebig)
only_if_absent boolean Nur schreiben, wenn der Schlüssel nicht existiert (Alias für if_none_match = "*")

Ein bedingter Schreibvorgang mit nicht erfüllter Vorbedingung gibt einen precondition_failed-Fehler zurück.

Objekte herunterladen

Objekt in einen Datei-Writer herunterladen:

local fs = require("fs")
local storage, storage_err = cloudstorage.get("app.infra:files")
if storage_err then return nil, storage_err end
local vol, fs_err = fs.get("app:temp")
if fs_err then
    storage:release()
    return nil, fs_err
end

local file, open_err = vol:open("/downloaded.json", "w")
if open_err then
    storage:release()
    return nil, open_err
end
local ok, err = storage:download_object("reports/daily.json", file)
local _, close_err = file:close()
if err then
    if close_err then report_cleanup_error(close_err) end
    storage:release()
    return nil, err
end
if close_err then
    storage:release()
    return nil, close_err
end

-- Download partial content (first 1KB)
local partial, partial_open_err = vol:open("/partial.bin", "w")
if partial_open_err then
    storage:release()
    return nil, partial_open_err
end
local partial_ok, partial_err = storage:download_object("backups/large-file.bin", partial, {
    range = "bytes=0-1023"
})
local _, partial_close_err = partial:close()

storage:release()
if partial_err then
    if partial_close_err then report_cleanup_error(partial_close_err) end
    return nil, partial_err
end
if partial_close_err then return nil, partial_close_err end
return partial_ok
Parameter Typ Beschreibung
key string Herunterzuladender Objektschlüssel
writer Writer Ziel-Datei-Writer
options.range string Byte-Bereich (z.B. "bytes=0-1023")
options.if_match string Nur herunterladen, wenn das Objekt-ETag übereinstimmt
options.if_none_match string Nur herunterladen, wenn das ETag nicht übereinstimmt

Gibt zurück: boolean, error

Eine fehlgeschlagene Vorbedingung (if_match/if_none_match) gibt einen precondition_failed-Fehler zurück.

Objekte auflisten

Objekte mit optionaler Präfix-Filterung auflisten:

local storage, storage_err = cloudstorage.get("app.infra:files")
if storage_err then return nil, storage_err end

local result, err = storage:list_objects({
    prefix = "reports/2024/",
    max_keys = 100
})
if err then
    storage:release()
    return nil, err
end

for _, obj in ipairs(result.objects) do
    print(obj.key, obj.size, obj.etag)
end

-- Paginate through large results
local token = nil
repeat
    local page, page_err = storage:list_objects({
        prefix = "logs/",
        max_keys = 1000,
        continuation_token = token
    })
    if page_err then
        storage:release()
        return nil, page_err
    end
    for _, obj in ipairs(page.objects) do
        process(obj)
    end
    token = page.next_continuation_token
    if not page.is_truncated then break end
until false

storage:release()
Parameter Typ Beschreibung
options.prefix string Nach Schlüssel-Präfix filtern
options.max_keys integer Maximale Anzahl zurückzugebender Objekte
options.continuation_token string Paginierungs-Token
options.include_owner boolean Den owner jedes Objekts einbeziehen (id, display_name)
options.include_versions boolean Objektversionen auflisten; jedes Element enthält version_id

Gibt zurück: table, error

Ergebnis enthält objects, is_truncated, next_continuation_token. Jedes Objekt hat key, size, etag, storage_class sowie optional last_modified, version_id und owner.

In Listenergebnissen ist content_type immer leer — S3-Listenoperationen geben ihn nicht zurück. Verwenden Sie head_object, um den Content-Type und die Metadaten eines Objekts zu lesen.

Objekt-Metadaten

Die Metadaten eines einzelnen Objekts abrufen, ohne dessen Body herunterzuladen:

local storage, storage_err = cloudstorage.get("app.infra:files")
if storage_err then return nil, storage_err end

local meta, err = storage:head_object("reports/daily.json")
if err then
    storage:release()
    return nil, err
end

print(meta.size, meta.etag, meta.content_type)
for k, v in pairs(meta.metadata) do
    print("meta", k, v)
end

storage:release()
Parameter Typ Beschreibung
key string Objektschlüssel

Gibt zurück: table, error

Ergebnisfelder:

Feld Typ Beschreibung
size integer Objektgröße in Bytes
etag string Entity-Tag
content_type string MIME-Typ
cache_control string Cache-Control-Header
content_disposition string Content-Disposition-Header
content_encoding string Content-Encoding-Header
storage_class string Speicherklasse
version_id string Versions-ID (vorhanden, wenn Versionierung aktiviert ist)
last_modified integer Zeitpunkt der letzten Änderung (Unix-Sekunden)
metadata table Benutzer-Metadaten (x-amz-meta-*)
headers table Rohe Response-Header (kleingeschriebene Schlüssel)

Ein fehlendes Objekt gibt einen not_found-Fehler zurück.

Objekte löschen

Mehrere Objekte entfernen:

local storage, storage_err = cloudstorage.get("app.infra:files")
if storage_err then return nil, storage_err end

local deleted, err = storage:delete_objects({
    "temp/file1.txt",
    "temp/file2.txt",
    "temp/file3.txt"
})

storage:release()
if err then return nil, err end
return deleted
Parameter Typ Beschreibung
keys string[] Array von zu löschenden Objektschlüsseln

Gibt zurück: boolean, error

Jeder Schlüssel wird versucht. Das Löschen eines nicht existierenden Schlüssels ist kein Fehler. Meldet der Provider Fehler pro Schlüssel, gibt der Aufruf einen einzelnen Fehler zurück, der jeden fehlgeschlagenen Schlüssel und seinen Provider-Fehlercode nennt.

Download-URLs

Erstellen Sie eine temporäre URL, die das Herunterladen eines Objekts ohne Anmeldeinformationen ermöglicht. Nützlich zum Teilen von Dateien mit externen Benutzern oder zum Bereitstellen von Inhalten über Ihre Anwendung.

local storage, err = cloudstorage.get("app.infra:files")
if err then
    return nil, err
end

local url, err = storage:presigned_get_url("reports/quarterly.pdf", {
    expiration = 3600
})

storage:release()

if err then
    return nil, err
end

-- Return URL to client for direct download
return {download_url = url}
Parameter Typ Beschreibung
key string Objektschlüssel
options.expiration integer Sekunden bis URL abläuft (Standard: 3600)

Gibt zurück: string, error

Upload-URLs

Erstellen Sie eine temporäre URL, die das Hochladen eines Objekts ohne Anmeldeinformationen ermöglicht. Ermöglicht Clients, Dateien direkt in den Speicher hochzuladen, ohne über Ihren Server zu proxyen.

local storage, err = cloudstorage.get("app.infra:files")
if err then
    return nil, err
end

local url, err = storage:presigned_put_url("uploads/user-123/avatar.jpg", {
    expiration = 600,
    content_type = "image/jpeg",
    content_length = 1024 * 1024
})

storage:release()

if err then
    return nil, err
end

-- Return URL to client for direct upload
return {upload_url = url}
Parameter Typ Beschreibung
key string Objektschlüssel
options.expiration integer Sekunden bis URL abläuft (Standard: 3600)
options.content_type string Erforderlicher Content-Type für Upload
options.content_length integer Erwartete Upload-Größe in Bytes

Gibt zurück: string, error

Multipart-Uploads

Ein einzelnes vorsigniertes PUT begrenzt ein Objekt auf 5 GiB. Ein vorsignierter Multipart-Upload teilt ein größeres Objekt in Teile, die ein Client direkt hochlädt und die dann serverseitig zusammengesetzt werden. Multipart ist eine Fähigkeit des Providers: S3 implementiert sie, Provider ohne sie geben errors.UNAVAILABLE zurück.

local storage = cloudstorage.get("app.infra:files")

local mp, err = storage:create_multipart_upload("backups/huge.zip", {
    content_type = "application/zip",
    metadata = { source = "uploader" },
})
if err then return nil, err end

local urls, err = storage:presigned_part_urls("backups/huge.zip", mp.upload_id, {
    count = 3,
    expiration = 900,
})
if err then
    storage:abort_multipart_upload("backups/huge.zip", mp.upload_id)
    return nil, err
end

-- Der Client sendet jede URL per PUT und liefert das ETag aus den Response-Headern zurück.
local done, err = storage:complete_multipart_upload("backups/huge.zip", mp.upload_id, {
    { part_number = 1, etag = etag1 },
    { part_number = 2, etag = etag2 },
    { part_number = 3, etag = etag3 },
})

storage:release()

create_multipart_upload

Startet einen Multipart-Upload für einen Schlüssel.

Parameter Typ Beschreibung
key string Objektschlüssel des finalen Objekts
options table content_type, cache_control, content_disposition, content_encoding, metadata, headers - dieselbe Semantik wie bei upload_object

Gibt zurück: table, error - die Tabelle enthält upload_id, das den Upload für jeden späteren Part-, Complete- und Abort-Aufruf identifiziert.

Bedingte Schreibvorgänge (if_match, if_none_match, only_if_absent) sind nicht Teil des Multipart-Protokolls und werden hier nicht akzeptiert.

presigned_part_urls

Erzeugt vorsignierte PUT-URLs für Teile eines laufenden Uploads. Jede URL wird mit einem einfachen HTTP-PUT beschrieben; der Uploader muss den ETag-Response-Header jedes Teils für complete_multipart_upload aufbewahren.

Parameter Typ Standard Beschreibung
key string erforderlich Objektschlüssel
upload_id string erforderlich Aus create_multipart_upload
options.parts int[] - Explizite Teilnummern (1-10000, keine Duplikate)
options.count int - Teile 1..count vorsignieren
options.headers table - Header, die bei jeder Part-Anfrage erforderlich sind; sie werden signiert und müssen vom Uploader ebenfalls gesendet werden
options.expiration int 3600 Sekunden bis zum Ablauf der URLs

Genau eines von parts oder count ist erforderlich, und ein einzelner Aufruf signiert höchstens 1000 URLs vor - bei sehr großen Objekten seitenweise vorsignieren.

Gibt zurück: table, error - ein Array von { part_number, url }.

Jeder Teil außer dem letzten muss mindestens 5 MiB groß sein; der Provider erzwingt dies beim Abschluss.

complete_multipart_upload

Setzt das finale Objekt aus seinen hochgeladenen Teilen zusammen. Teile können in beliebiger Reihenfolge gemeldet werden und werden vor dem Abschluss nach Teilnummer sortiert.

Parameter Typ Beschreibung
key string Objektschlüssel
upload_id string Aus create_multipart_upload
parts table Array von { part_number = int, etag = string }

Gibt zurück: table, error - etag, dazu version_id und location, sofern der Provider sie meldet. Eine unbekannte Upload-ID gibt errors.NOT_FOUND zurück.

abort_multipart_upload

Verwirft einen laufenden Upload und gibt seine gespeicherten Teile frei.

Parameter Typ Beschreibung
key string Objektschlüssel
upload_id string Aus create_multipart_upload

Gibt zurück: boolean, error

Ein Upload, der nie abgeschlossen wird, hält seine Teile gespeichert - und abrechnungsrelevant -, bis er abgebrochen wird. Auf jedem Fehlerpfad abbrechen und als Absicherung eine Bucket-Lifecycle-Regel konfigurieren - siehe Cloud-Speicher.

Bereichs-Reader

open_reader öffnet wahlfreien Zugriff auf ein Objekt über Ranged-GETs - ohne lokales Zwischenspeichern und ohne vollständigen Download. Der Hauptkonsument ist archive.open, das mehrere GB große Archive mit begrenztem Speicher direkt aus dem Objektspeicher liest.

local archive = require("archive")
local storage = cloudstorage.get("app.infra:files")

local reader, err = storage:open_reader("uploads/huge.zip", {
    block_size = 8 * 1024 * 1024,
    cache_blocks = 4,
})
if err then return nil, err end

local r = assert(archive.open(reader))
for e in r:entries() do
    print(e.name, e.size)
end
r:close()
reader:close()

storage:release()
Parameter Typ Standard Beschreibung
key string erforderlich Objektschlüssel
options.block_size int 8388608 Einheit des Ranged-GET in Bytes (64 KiB bis 128 MiB)
options.cache_blocks int 4 Im Speicher gehaltene LRU-Blöcke (1 bis 64)

block_size * cache_blocks darf 256 MiB nicht überschreiten. Ein fehlendes Objekt gibt errors.NOT_FOUND zurück.

Gibt zurück: Reader, error

Das ETag des Objekts wird beim Öffnen des Readers fixiert und bei jedem Bereichs-Lesevorgang als If-Match gesendet, sodass ein während des Lesens überschriebenes Objekt den Lesevorgang mit dem Vorbedingungsfehler des Providers fehlschlagen lässt, statt eine Mischung aus zwei Objektgenerationen zu liefern; archive gibt ihn als errors.INTERNAL weiter. Ein Provider, der kein ETag liefern kann, gibt errors.UNAVAILABLE zurück; der Reader liefert nie ein nicht fixiertes Objekt.

Lesevorgänge mit Cache-Miss führen blockierende Netzwerk-IO in der aufrufenden Task aus und serialisieren gleichzeitige Reader, sodass sequenzieller Zugriff pro Eintrag - das Archiv-Muster - die vorgesehene Form ist.

Reader-Methoden

Methode Gibt zurück Beschreibung
size() integer Objektgröße in Bytes, aus dem Stat beim Öffnen
key() string Objektschlüssel, aus dem der Reader liest
close() boolean, error Blockcache freigeben; idempotent

Der Reader wird am Ende des Task-Scopes automatisch geschlossen, wenn er nicht explizit geschlossen wird.

Storage-Methoden

Methode Gibt zurück Beschreibung
upload_object(key, content, opts?) boolean, error String- oder Dateiinhalt hochladen
download_object(key, writer, opts?) boolean, error In Datei-Writer herunterladen
head_object(key) table, error Objekt-Metadaten abrufen
list_objects(opts?) table, error Objekte mit Präfix-Filter auflisten
delete_objects(keys) boolean, error Mehrere Objekte löschen
presigned_get_url(key, opts?) string, error Temporäre Download-URL generieren
presigned_put_url(key, opts?) string, error Temporäre Upload-URL generieren
create_multipart_upload(key, opts?) table, error Einen vorsignierten Multipart-Upload starten
presigned_part_urls(key, upload_id, opts) table, error PUT-URLs für Upload-Teile vorsignieren
complete_multipart_upload(key, upload_id, parts) table, error Das Objekt aus den hochgeladenen Teilen zusammensetzen
abort_multipart_upload(key, upload_id) boolean, error Einen laufenden Multipart-Upload verwerfen
open_reader(key, opts?) Reader, error Einen Bereichs-Reader mit wahlfreiem Zugriff öffnen
release() boolean Speicherressource freigeben

Berechtigungen

Cloud-Speicheroperationen unterliegen der Auswertung der Sicherheitsrichtlinien.

Aktion Ressource Beschreibung
cloudstorage.get Speicher-ID Eine Speicherressource abrufen

Fehler

Bedingung Art Wiederholbar
Leere Ressourcen-ID errors.INVALID nein
Ressource nicht gefunden errors.NOT_FOUND nein
Keine Cloud-Speicherressource errors.INVALID nein
Speicher freigegeben errors.INVALID nein
Leerer Schlüssel errors.INVALID nein
Inhalt nil errors.INVALID nein
Writer nicht gültig errors.INVALID nein
Objekt nicht gefunden errors.NOT_FOUND nein
Unbekannte Upload-ID errors.NOT_FOUND nein
Bedingte Vorbedingung fehlgeschlagen errors.CONFLICT nein
Objekt während eines Bereichs-Lesevorgangs überschrieben (von archive weitergegeben) errors.INTERNAL nein
Provider unterstützt keine Multipart-Uploads errors.UNAVAILABLE nein
Provider liefert kein ETag für open_reader errors.UNAVAILABLE nein
Berechtigung verweigert wird als Lua-Fehler ausgelöst, nicht zurückgegeben -
Provider-Operation fehlgeschlagen errors.UNKNOWN nicht gesetzt

Informationen zum Umgang mit Fehlern finden Sie unter Fehlerbehandlung.