Dateien mit cURL und vorsignierten PUT-URLs zu MinIO hochladen
Um eine lokale Datei zu MinIO zu exportieren, erzeugen Sie eine vorsignierte PUT-URL für einen
Bucket und einen Objektschlüssel. Senden Sie die Datei dann mit curl --upload-file.
Diese Anleitung erstellt einen lokalen Server und den Bucket und lädt das hochgeladene Objekt
herunter, um dessen Bytes mit Ihrer Datei zu vergleichen.
Verstehen, was die URL autorisiert
MinIO stellt eine S3-kompatible HTTP-API bereit. Ein SDK signiert eine Anfrage mit Ihrem
Zugriffsschlüssel und Ihrem geheimen Schlüssel; cURL sendet die Bytes mithilfe dieser Signatur.
Das SDK und der Befehlszeilenclient mc sind Werkzeuge, keine separaten
Authentifizierungsmethoden.
Eine vorsignierte URL ist ein Bearer-Zugangsdatum. Alle, die die URL aus diesem Beispiel besitzen, können 10 Minuten lang per PUT an genau diesen Objektschlüssel schreiben und dabei auch dessen Bytes ersetzen. Die URL authentifiziert nicht den Inhalt einer bestimmten lokalen Datei. Halten Sie sie aus dem Shell-Verlauf, aus Logs und aus geteilten Nachrichten heraus. Ein Formular-Upload mit POST-Policy ist ein anderer Vorgang; verwenden Sie die SDK-Operation für vorsignierte PUT-Anfragen.
Eine lokale Demo vorbereiten
Das MinIO-Community-Repository wurde am 25. April 2026 archiviert und weist darauf hin, dass es nicht mehr gepflegt wird. Der folgende Build aus festgelegtem Quellcode dient lokalen Kompatibilitätstests und ist keine Empfehlung für eine neue Produktivbereitstellung. Verwenden Sie im Produktivbetrieb einen gepflegten Dienst und beachten Sie dessen Anforderungen an Authentifizierung und TLS.
Voraussetzungen
Verwenden Sie Linux mit Bash, cURL, Go 1.26.8, Node.js 24.15.0 und Corepack mit Yarn 4.12.0.
Die Beispiele nutzen die integrierte TypeScript-Unterstützung von Node;
Dateien mit der Endung .mts laufen auch in einem übergeordneten
CommonJS-Projekt als ES-Module. Für den Server ist RELEASE.2025-10-15T17-29-55Z festgelegt,
für das JavaScript-SDK minio@8.0.7. Der Server-Build benötigt Netzwerkzugriff,
Festplattenspeicher für Go-Abhängigkeiten und einige Minuten zum Kompilieren.
Beginnen Sie in einem beschreibbaren Verzeichnis. Der folgende Block erstellt ein neues
Verzeichnis minio-curl-demo und installiert darin ein eigenes SDK. Bei einem
bereits vorhandenen Verzeichnis bricht er ab. Seine Lockdatei macht es zu einem
separaten Yarn-Projekt. Die Paket- und Cache-Einstellungen halten
die Installation lokal in diesem Verzeichnis. Die übergeordnete Shell bleibt in ihrem
ursprünglichen Verzeichnis.
(
mkdir minio-curl-demo &&
cd minio-curl-demo &&
printf '%s\n' '{"name":"minio-curl-demo","private":true,"packageManager":"yarn@4.12.0","dependencies":{"minio":"8.0.7"}}' > package.json &&
touch yarn.lock &&
printf 'nodeLinker: node-modules\nenableGlobalCache: false\n' > .yarnrc.yml &&
env COREPACK_HOME="$PWD/.corepack" YARN_IGNORE_PATH=1 \
YARN_GLOBAL_FOLDER="$PWD/.yarn/global" corepack yarn install
)
Ersteinrichtung
Kompilieren Sie den festgelegten Server-Quellcode in das
Verzeichnis bin der Demo. Führen Sie dies im selben übergeordneten
Verzeichnis wie den vorherigen Block aus. Falls die Kompilierung fehlschlägt, stoppen Sie hier;
starten Sie keine übrig gebliebene Binärdatei aus einem früheren Build.
(
cd minio-curl-demo &&
mkdir bin data go-path go-cache tmp &&
env GOENV=off GOWORK=off GOTOOLCHAIN=local \
GOPATH="$PWD/go-path" GOCACHE="$PWD/go-cache" GOTMPDIR="$PWD/tmp" \
GOBIN="$PWD/bin" go install github.com/minio/minio@RELEASE.2025-10-15T17-29-55Z
)
Öffnen Sie zwei Bash-Terminals in diesem übergeordneten Verzeichnis. Fügen Sie diese Einstellungen in beide Terminals ein. Wählen Sie zwei freie Ports, falls diese belegt sind, und verwenden Sie in beiden Terminals dieselben Werte. Die Zugangsdaten sind bewusst öffentliche Demowerte; verwenden Sie sie nur mit diesem Server, der ausschließlich über Loopback erreichbar ist.
export MINIO_API_PORT=19000
export MINIO_CONSOLE_PORT=19001
export MINIO_ENDPOINT="http://127.0.0.1:${MINIO_API_PORT}"
export MINIO_ACCESS_KEY='curl-demo-admin'
export MINIO_SECRET_KEY='local-demo-only-password'
Starten Sie den Server im ersten Terminal im Vordergrund. Lassen Sie ihn laufen, während Sie das
zweite Terminal verwenden. Drücken Sie zum Abschluss im ersten Terminal Strg+C, um ihn zu stoppen;
die Shell läuft weiter und die Objekte bleiben in minio-curl-demo/data.
(
cd minio-curl-demo &&
MINIO_ROOT_USER="$MINIO_ACCESS_KEY" MINIO_ROOT_PASSWORD="$MINIO_SECRET_KEY" \
./bin/minio server ./data --address "127.0.0.1:${MINIO_API_PORT}" \
--console-address "127.0.0.1:${MINIO_CONSOLE_PORT}"
)
Bucket und Signierer erstellen
Speichern Sie jede der folgenden TypeScript-Dateien innerhalb von
minio-curl-demo. Der gemeinsame Client prüft, ob der Endpunkt ein Origin ohne
Pfadpräfix oder eingebettete Zugangsdaten ist. Seine Region entspricht der dieses lokalen
Servers. Verwenden Sie für eine bestehende Bereitstellung deren tatsächliche Region und
Zugangsdaten, die auf den Bucket beschränkt sind; die Root-Zugangsdaten hier dienen nur der
Einrichtung der privaten Demo.
Speichern Sie die Datei als minio-client.mts:
import { Client } from 'minio'
export function createClient(): Client {
const { MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY } = process.env
if (!MINIO_ENDPOINT || !MINIO_ACCESS_KEY || !MINIO_SECRET_KEY) {
throw new Error('Set the endpoint and credentials')
}
const endpoint = new URL(MINIO_ENDPOINT)
if (!['http:', 'https:'].includes(endpoint.protocol) || endpoint.username ||
endpoint.password || endpoint.pathname !== '/' || endpoint.search || endpoint.hash) {
throw new Error('Use an HTTP or HTTPS origin without credentials or a path prefix')
}
return new Client({
endPoint: endpoint.hostname,
port: Number(endpoint.port || (endpoint.protocol === 'https:' ? 443 : 80)),
useSSL: endpoint.protocol === 'https:',
accessKey: MINIO_ACCESS_KEY,
secretKey: MINIO_SECRET_KEY,
region: 'us-east-1',
})
}
Speichern Sie die Datei als prepare-bucket.mts. Das Signieren einer URL erstellt
keinen Bucket; das übernimmt dieser Schritt.
import { createClient } from './minio-client.mts'
async function main(): Promise<void> {
const [bucket, ...extra] = process.argv.slice(2)
if (!bucket || extra.length) throw new Error('Usage: node prepare-bucket.mts BUCKET')
const client = createClient()
if (!(await client.bucketExists(bucket))) await client.makeBucket(bucket, 'us-east-1')
console.log(`Bucket ready: ${bucket}`)
}
main().catch(() => {
console.error('Bucket setup failed; check the server, credentials, and bucket name')
process.exitCode = 1
})
Erstellen Sie den Bucket im zweiten Terminal. Ein erfolgreicher Durchlauf gibt
Bucket ready: curl-demo aus. Falls der Server noch nicht bereit ist, warten Sie auf seine
Startmeldung und führen Sie diesen Befehl erneut aus.
(cd minio-curl-demo && node prepare-bucket.mts curl-demo)
Vorsignierte URLs erzeugen
Speichern Sie die Datei als presign.mts. Sie signiert entweder PUT oder GET
und gibt eine cURL-Konfigurationszeile aus, die die Befehle zum Hochladen und Verifizieren über
die Standardeingabe weiterreichen. Beide Vorgänge verwenden eine Gültigkeitsdauer von 600 Sekunden.
Die SDK-API-Referenz dokumentiert diese beiden unterschiedlichen
Methoden.
import { createClient } from './minio-client.mts'
async function main(): Promise<void> {
const [method, bucket, key, ...extra] = process.argv.slice(2)
if (!bucket || !key || extra.length || !['put', 'get'].includes(method ?? '')) {
throw new Error('Usage: node presign.mts put|get BUCKET KEY')
}
const client = createClient()
const url = method === 'put'
? await client.presignedPutObject(bucket, key, 600)
: await client.presignedGetObject(bucket, key, 600)
console.log(`url = ${JSON.stringify(url)}`)
}
main().catch(() => {
console.error('Signing failed; check the method, bucket, key, endpoint, and credentials')
process.exitCode = 1
})
Führen Sie den Signierer nicht allein in einem Terminal aus, dessen Ausgabe aufgezeichnet wird: Seine Ausgabe enthält die vorsignierte URL. Das SDK nimmt die URL-Kodierung des Objektschlüssels vor. Übergeben Sie den ursprünglichen Schlüssel an den Signierer und lassen Sie die erzeugte URL unverändert, einschließlich Host, Port, Pfad und Abfragezeichenfolge.
Eine Datei hochladen und das Ergebnis protokollieren
Speichern Sie die Datei als upload.sh im Demo-Verzeichnis. Führen Sie sie
mit Bash aus; binden Sie sie nicht per source ein. Sie akzeptiert eine reguläre lokale Datei,
einen Bucket und einen expliziten Objektschlüssel. Leere Dateien sind gültig. Stellen Sie
Dateinamen wie - oder -report.bin das Präfix
./ voran, damit sie Dateien statt der Standardeingabe von cURL bezeichnen.
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 3 ] || [ ! -f "$1" ] || [ ! -r "$1" ] || [ "$1" = '-' ]; then
printf 'Usage: bash upload.sh FILE BUCKET KEY (readable regular file)\n' >&2
exit 1
fi
file=$1
bucket=$2
key=$3
configuration=$(node presign.mts put "$bucket" "$key") || exit 1
if printf '%s\n' "$configuration" |
curl -q --config - --globoff --path-as-is --fail --silent \
--connect-timeout 5 --max-time 120 --upload-file "$file" \
--output /dev/null --write-out 'HTTP %{http_code}\n' 2>/dev/null |
tee -a upload.log; then
printf 'Uploaded %s to %s/%s\n' "$file" "$bucket" "$key"
else
printf 'Upload or status logging failed for %s; verify the object before retrying\n' "$file" >&2
exit 1
fi
-q ist die erste Option von cURL, damit es die
.curlrc des Aufrufers ignoriert. --config - liest die URL
von der Standardeingabe und hält sie so aus den Prozessargumenten von cURL heraus.
--globoff behandelt eckige und geschweifte Klammern in Dateinamen wörtlich.
--fail lässt die Übertragung bei einer HTTP-Ablehnung fehlschlagen, und
pipefail bewahrt Übertragungs- oder Protokollierungsfehler durch die Pipeline
hindurch. Die Zuweisung prüft den Signierer separat. Das Skript unterdrückt rohe
Übertragungsdiagnosen und protokolliert nur den HTTP-Status, nicht den Antwortkörper oder die URL.
Syntax und Optionen zur Konfiguration finden Sie im
cURL-Handbuch.
Führen Sie dies im zweiten Terminal aus dem übergeordneten Verzeichnis aus. Der Befehl erstellt
oder ersetzt die lokale Demodatei sample.txt und lädt sie unter einem Schlüssel
hoch, der Leerzeichen und ein Pluszeichen enthält:
(
cd minio-curl-demo &&
printf 'hello, MinIO\n' > sample.txt &&
bash upload.sh sample.txt curl-demo 'exports/sample + 1.txt'
)
Erwarten Sie HTTP 200, gefolgt von Uploaded sample.txt to curl-demo/exports/sample + 1.txt.
Der Bucket ist nicht versioniert: Ein erfolgreicher PUT an einen bestehenden Schlüssel
ersetzt dessen bisherige Bytes. Wählen Sie einen neuen Schlüssel, wenn Sie das alte Objekt
behalten möchten. Bei einer abgelaufenen URL, einer ungültigen Signatur oder einem fehlenden
Bucket muss der Vorgang ohne die Meldung Uploaded fehlschlagen.
Die gespeicherten Bytes herunterladen und vergleichen
HTTP 200 bestätigt, dass der Server den PUT akzeptiert hat. Prüfen Sie das gespeicherte Objekt
separat mit einem signierten GET. Dieser Block schreibt downloaded.txt und ersetzt
diese lokale Datei, wenn der Download erfolgt. Anschließend vergleicht er sie mit
sample.txt. Bei erfolgreichem Vergleich wird
Verified identical bytes ausgegeben.
(
set -euo pipefail
cd minio-curl-demo || exit 1
configuration=$(node presign.mts get curl-demo 'exports/sample + 1.txt') || exit 1
if printf '%s\n' "$configuration" |
curl -q --config - --globoff --path-as-is --fail --silent \
--connect-timeout 5 --max-time 120 --output downloaded.txt 2>/dev/null; then
cmp sample.txt downloaded.txt && printf 'Verified identical bytes\n'
else
printf 'Download failed; check the object and signing configuration\n' >&2
exit 1
fi
)
Einen fehlgeschlagenen Upload diagnostizieren
Falls das Signieren fehlschlägt, prüfen Sie die Umgebungseinstellungen und alle drei
Skriptargumente. Ein Endpunkt mit einem Proxy-Pfadpräfix wie https://storage.example.com/minio/ wird
abgelehnt. Verwenden Sie den Origin der S3-API des Dienstes und HTTPS für einen entfernten Endpunkt.
HTTP 000 bedeutet, dass keine HTTP-Antwort empfangen wurde. Prüfen Sie,
ob der Server auf dem konfigurierten Port läuft, die Datei lesbar ist und das Zertifikat als
vertrauenswürdig gilt. Deaktivieren Sie die Zertifikatsprüfung nicht, um einen Upload an einen
entfernten Endpunkt zu ermöglichen. HTTP 403 kann auf eine ungültige oder
abgelaufene Signatur, falsche Zugangsdaten, verweigerte Berechtigungen oder abweichende Systemzeiten
hinweisen. HTTP 404 kann auf einen fehlenden Bucket hinweisen; der Signierer
kann eine URL für einen Bucket erzeugen, der nicht existiert.
Ein Protokollierungsfehler kann auftreten, nachdem der Server das Objekt gespeichert hat.
Beispielsweise könnte upload.log ein Verzeichnis oder nicht beschreibbar sein.
Das Skript meldet einen Fehler, weil es den Status nicht aufzeichnen konnte; prüfen Sie den
Zustand mit GET, bevor Sie sich für einen erneuten Versuch entscheiden. Auch nach einem
Verbindungsabbruch beim Client kann das Ergebnis ungewiss sein. Die erneute Verwendung desselben
Schlüssels kann ein bereits akzeptiertes Objekt ersetzen.
Den nächsten Schritt wählen
Dieses Skript sendet eine Datei in einem PUT mit einem Übertragungszeitlimit von 120 Sekunden. Es implementiert weder mehrteilige Uploads noch fortsetzbare Übertragungen oder Verzeichnissynchronisierung. Verwenden Sie dafür ein SDK oder einen Speicherclient mit dem benötigten Verhalten und prüfen Sie dessen Ersetzungsrichtlinie. Einen AWS-spezifischen Stapelverarbeitungsablauf finden Sie unter Stapelexporte zu Amazon S3 mit cURL und der AWS CLI.
