Dateiexport nach Amazon S3 in Node.js: vollständige Anleitung
Verwenden Sie PutObjectCommand für einen einzelnen Upload und
Upload aus @aws-sdk/lib-storage für Multipart-Uploads.
Die folgende CLI exportiert eine lokale Datei nach Amazon S3, lädt das resultierende Objekt herunter
und prüft dessen SHA-256, Größe und Metadaten, bevor sie Erfolg meldet. Beide Upload-Verfahren
geben bei einem fehlgeschlagenen Upload oder einer fehlgeschlagenen Verifizierung einen
Fehler-Exit-Status zurück.
Voraussetzungen
Sie benötigen Bash unter Linux, Node.js, separat installiertes Corepack und einen vorhandenen privaten S3-Bucket für allgemeine Zwecke. Dieses Beispiel wurde mit Node.js 24.21.0 und 26.8.1, Corepack 0.36.0, Yarn 4.12.0 und AWS-SDK-Paketen 3.1149.0 getestet. Verwenden Sie eine weiterhin gepflegte Version von Node.js 24 LTS oder 26. Dies sind getestete Versionen, keine grundsätzlichen Mindestversionen für das SDK. Node.js 26 enthält Corepack nicht.
Verwenden Sie eine reguläre lokale Datei und ändern Sie deren Inhalt erst, wenn die Verifizierung
abgeschlossen ist. Setzen Sie ihren Pfad beim CLI-Aufruf in Anführungszeichen. Leerzeichen,
literale Prozentzeichen und Unicode-Zeichen außerhalb der Basisebene werden unterstützt. Pfade
mit dem Unicode-Ersatzzeichen U+FFFD werden abgewiesen, auch wenn ein
gültiger Dateiname dieses Zeichen enthält. Node.js kann ungültige native Argumentbytes durch
dieses Zeichen ersetzen, wodurch zwei unterschiedliche Dateinamen nicht mehr unterscheidbar sind.
Benennen Sie solche Dateien vor der Verwendung dieser CLI um.
Wählen Sie einen noch nicht verwendeten Objektschlüssel unter einem Präfix, das Ihnen gehört.
Dieses Beispiel verweigert das Ersetzen eines vorhandenen Objekts. Die verwendeten Zugangsdaten
benötigen s3:PutObject für Uploads, s3:GetObject für die
Verifizierung und s3:AbortMultipartUpload für das Bereinigen nach Multipart-Fehlern.
AWS-Zugangsdaten einrichten
Das SDK verwendet seine Standardkette von Zugangsdatenanbietern.
Verwenden Sie lokal ein vorhandenes authentifiziertes AWS-Profil oder auf AWS eine IAM-Rolle.
Temporäre Zugangsdaten aus Umgebungsvariablen funktionieren ebenfalls. Sie benötigen zusätzlich
zum Zugriffsschlüssel und geheimen Schlüssel auch AWS_SESSION_TOKEN.
Schreiben Sie Zugangsdaten weder in das Programm noch in einen Commit des Projekts.
Die folgenden Befehle lesen die Region des Buckets aus AWS_REGION.
Für ein benanntes gemeinsames Profil setzen Sie AWS_PROFILE in der Shell,
die die Befehle ausführt. Wenn Zugangsdaten ablaufen, erneuern Sie diese vor einem erneuten Versuch
über Ihr übliches Authentifizierungsverfahren. Das Beispiel erstellt keinen Bucket und
konfiguriert IAM nicht.
AWS SDK installieren und verwenden
Fügen Sie diesen Block in dem Verzeichnis ein, in dem Sie ein neues Projekt namens
s3-export erstellen möchten. Er prüft jede ausführbare Datei, bevor er
Dateien erstellt, und läuft in einer Subshell. Dadurch bleiben Verzeichnis und Optionen der
aufrufenden Shell unverändert. Ein vorhandenes Verzeichnis namens s3-export
stoppt die Einrichtung, bevor Dateien überschrieben werden.
(
set -eu
command -v node >/dev/null || { printf 'Install Node.js first.\n' >&2; exit 1; }
command -v corepack >/dev/null || { printf 'Install Corepack first.\n' >&2; exit 1; }
mkdir s3-export
cd s3-export
cat > package.json <<'JSON'
{
"name": "s3-export",
"private": true,
"type": "module",
"packageManager": "yarn@4.12.0",
"dependencies": {
"@aws-sdk/client-s3": "3.1149.0",
"@aws-sdk/lib-storage": "3.1149.0"
}
}
JSON
touch yarn.lock
corepack yarn install
)
Das lokale Manifest und die Lockdatei geben diesem Unterprojekt eine eigene Paket- und
Modulgrenze, auch innerhalb eines npm- oder Yarn-Projekts. Yarn liest weiterhin die geltenden
Einstellungen für .yarnrc.yml im Home-Verzeichnis und in übergeordneten
Verzeichnissen. Prüfen Sie die tatsächlich verwendete Version mit corepack yarn --version
aus dem Verzeichnis s3-export; sie sollte 4.12.0 sein.
Wenn eine geerbte Einstellung für yarnPath, eine Registry-Richtlinie oder
eine Netzwerkrichtlinie die Installation verhindert, klären Sie diese mit der für das Projekt
verantwortlichen Person oder verwenden Sie ein Verzeichnis außerhalb dieser Konfiguration.
Umgehen Sie die Richtlinie nicht stillschweigend.
Wenn die Installation nach der Projekterstellung fehlschlägt, behalten Sie die Dateien und wiederholen Sie die Installation aus der aufrufenden Shell:
(cd s3-export && corepack yarn install)
Speichern Sie dieses vollständige Programm als s3-export/export.ts:
import { createHash } from 'node:crypto'
import { createReadStream } from 'node:fs'
import { stat } from 'node:fs/promises'
import { Readable } from 'node:stream'
import {
GetObjectCommand,
PutObjectCommand,
S3Client,
S3ServiceException,
type PutObjectCommandInput,
} from '@aws-sdk/client-s3'
import { Upload } from '@aws-sdk/lib-storage'
class ReaderError extends Error {}
async function digest(source: AsyncIterable<Uint8Array>): Promise<{ bytes: number; sha256: string }> {
const hash = createHash('sha256')
let bytes = 0
for await (const chunk of source) {
bytes += chunk.byteLength
hash.update(chunk)
}
return { bytes, sha256: hash.digest('hex') }
}
async function main(): Promise<{ bucket: string; key: string; bytes: number; sha256: string }> {
const [mode, file, bucket, key, ...extra] = process.argv.slice(2)
if (!['put', 'multipart', 'verify'].includes(mode ?? '') || !file || !bucket || !key || extra.length) {
throw new ReaderError('Usage: export.ts put|multipart|verify FILE BUCKET KEY')
}
if (file.includes('\uFFFD')) {
throw new ReaderError('FILE must not contain U+FFFD; rename the file before exporting it.')
}
const region = process.env.AWS_REGION
if (!region) throw new ReaderError('Set AWS_REGION to the bucket’s region.')
const info = await stat(file)
if (!info.isFile()) throw new ReaderError('FILE must be a regular file.')
const expected = await digest(createReadStream(file))
if (expected.bytes !== info.size) throw new ReaderError('The input changed while being read.')
const client = new S3Client({ region, maxAttempts: 1 })
try {
if (mode !== 'verify') {
const body = createReadStream(file)
try {
const params: PutObjectCommandInput = {
Bucket: bucket,
Key: key,
Body: body,
ContentLength: expected.bytes,
ContentType: 'application/octet-stream',
Metadata: { sha256: expected.sha256 },
ServerSideEncryption: 'AES256',
IfNoneMatch: '*',
}
if (mode === 'put') {
await client.send(new PutObjectCommand(params))
} else {
const upload = new Upload({
client,
params,
queueSize: 2,
leavePartsOnError: false,
})
upload.on('httpUploadProgress', ({ loaded, total }) => {
console.error(`Transferred ${loaded ?? 0}/${total ?? expected.bytes} bytes`)
})
await upload.done()
}
} finally {
body.destroy()
}
}
const stored = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }))
if (!(stored.Body instanceof Readable)) throw new ReaderError('No readable S3 response body.')
const actual = await digest(stored.Body)
if (
actual.bytes !== expected.bytes ||
actual.sha256 !== expected.sha256 ||
stored.ContentLength !== expected.bytes ||
stored.Metadata?.sha256 !== expected.sha256 ||
stored.ContentType !== 'application/octet-stream' ||
stored.ServerSideEncryption !== 'AES256'
) {
throw new ReaderError('Stored bytes or metadata do not match the input.')
}
return { bucket, key, ...actual }
} finally {
client.destroy()
}
}
main()
.then((outcome) => console.log(JSON.stringify(outcome)))
.catch((error: unknown) => {
if (error instanceof ReaderError) {
console.error(error.message)
} else {
const reason = error instanceof S3ServiceException ? error.name : 'LocalError'
console.error(`Export failed (${reason}). Check the file, region, credentials, and permissions.`)
}
process.exitCode = 1
})
Führen Sie Folgendes aus dem Verzeichnis aus, das s3-export enthält.
Ersetzen Sie Region, Bucket und Schlüssel durch Ihr eigenes Ziel. Die Beispieldatei wird nur
angelegt, wenn sie noch nicht existiert. Ein erneuter Aufruf erhält daher ihren Inhalt:
(
cd s3-export &&
(set -C; printf 'S3 export example\n' > sample.txt) &&
AWS_REGION=us-east-1 corepack yarn node export.ts put sample.txt YOUR_BUCKET exports/sample.txt
)
Ein erfolgreicher Durchlauf gibt JSON mit dem exakten Bucket, Schlüssel, der Byteanzahl und SHA-256 aus. Die Verifizierung liest das Objekt unter diesem Schlüssel wieder ein. Sie behandelt weder einen ETag noch die Upload-Antwort als Prüfsumme der lokalen Datei. Der Download verursacht eine zusätzliche Anfrage und liest alle Bytes erneut.
Große Dateien mit Multipart-Uploads verarbeiten
Die Multipart-Hilfsfunktion
teilt einen Stream in gepufferte Teile auf. Bei einer Eingabe mit bekannter Länge
wählt sie eine Teilgröße von mindestens 5 MiB, angepasst an die
maximale Anzahl der Teile. queueSize: 2 erlaubt den gleichzeitigen Upload von
zwei Teilen; die Datei wird nicht vollständig in den Arbeitsspeicher geladen. Kleine Eingaben,
auch leere Dateien, verwenden stattdessen einen einzelnen PUT.
Verwenden Sie dasselbe Programm und setzen Sie multipart anstelle von put ein:
(
cd s3-export &&
AWS_REGION=us-east-1 corepack yarn node export.ts multipart /path/to/large-file.zip YOUR_BUCKET exports/large-file.zip
)
Der Fortschritt wird auf stderr ausgegeben. Auch ein Fortschrittsereignis, das alle Bytes als
übertragen anzeigt, bedeutet noch keinen Abschluss: Das Programm wartet auf
upload.done() und verifiziert anschließend das gespeicherte Objekt.
leavePartsOnError: false fordert die Hilfsfunktion auf, nach einem fehlgeschlagenen
Teil-Upload abzubrechen. In dieser festgelegten Version bleibt bei einem Fehler von
CompleteMultipartUpload,
auch bei einer Schlüsselkollision, der unvollständige Upload bestehen.
Bitten Sie den Bucket-Eigentümer, diesen Upload zu prüfen und abzubrechen. Auch das Beenden des
Prozesses kann Teile zurücklassen.
S3 erlaubt bis zu 5 GB in einem PUT und bis zu 50 TB per Multipart-Upload. Die JavaScript-Hilfsfunktion und ihre maximale Anzahl von Teilen belegen jedoch nicht, dass jede maximale Objektgröße des Dienstes unterstützt wird. Für Objekte über 5 TB verweist die Upload-Anleitung von AWS auf den S3 Transfer Manager in Java, Python oder der AWS CLI. Diese Anleitung verifiziert das Verhalten einzelner Uploads und von Multipart-Uploads mit kleinen Fixtures; sie ist keine Anleitung für eine Übertragung von 50 TB.
Bewährte Verfahren für die Sicherheit
Halten Sie den Bucket privat und begrenzen Sie den Zugriff auf das vorgesehene Präfix. Für den Upload und die Verifizierung dieses Programms sowie die Multipart-Abbruchoperationen der Hilfsfunktion kann ein Administrator diese Richtlinie auf Objektebene gewähren. Dabei sind Bucket und Präfix zu ersetzen:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:AbortMultipartUpload"],
"Resource": "arn:aws:s3:::YOUR_BUCKET/exports/*"
}
]
}
Diese Berechtigungen entsprechen den
Anforderungen für Multipart-Operationen und den
GetObject-Anforderungen.
Bucket-Richtlinien können eine Anfrage dennoch verweigern. Das Programm verwendet HTTPS und
fordert mit AES256 explizit eine von S3 verwaltete Verschlüsselung an.
Es fordert keine öffentliche ACL an. Ein Bucket, der SSE-KMS erfordert, benötigt eine andere
Verschlüsselungskonfiguration und die geltenden KMS-Berechtigungen. Verwenden Sie daher die
Richtlinie dieses Buckets, statt diesem Beispiel weitreichende Berechtigungen hinzuzufügen.
Fehlerbehandlung und erneute Versuche
Die Bedingung IfNoneMatch: '*'
weist einen vorhandenen Schlüssel beim abschließenden Schreibvorgang des Uploads ab. Eine
Kollision führt zu einem Fehler und erhält das vorhandene Objekt. Verwenden Sie einen neuen
Schlüssel, statt fremde Daten zu entfernen. Beide Upload-Modi schlagen auch dann fehl, wenn
Zugangsdaten abgewiesen werden oder die angeforderte Datei fehlt.
maxAttempts: 1 begrenzt das SDK auf einen Versuch pro Anfrage. Die Einstellung
zählt die erste Anfrage mit, sodass ein höherer Wert erneute Versuche erlaubt. Ein bereits
verbrauchter Stream für einen einzelnen PUT kann nicht einfach erneut abgespielt werden.
Die Multipart-Hilfsfunktion puffert Teile, sodass das SDK diese Teilanfragen wiederholen kann.
Wenn Sie die gesamte CLI erneut ausführen, öffnet sie einen neuen Stream. Nach einem
fehlgeschlagenen Upload kann unklar sein, welches Ergebnis gespeichert wurde. Zudem kann die
Verifizierung fehlschlagen, nachdem der Upload erfolgreich war. Prüfen Sie vor einem erneuten
Versuch genau diesen Schlüssel. Um ohne erneuten Upload zu verifizieren, führen Sie Folgendes aus:
(
cd s3-export &&
AWS_REGION=us-east-1 corepack yarn node export.ts verify sample.txt YOUR_BUCKET exports/sample.txt
)
Dies prüft Bytes und Metadaten anhand der aktuellen lokalen Datei und beendet sich bei einer Abweichung mit einem Exit-Status ungleich null. Es löscht kein abweichendes Objekt und macht keinen abgeschlossenen Upload rückgängig.
TypeScript-Unterstützung
Node.js führt diese Datei mit nativem Entfernen der Typangaben aus.
Die Einrichtung deklariert "type": "module", und corepack yarn node
stellt den Abhängigkeitsloader von Yarn bereit, auch in Plug’n’Play-Projekten. Weder
tsx noch ts-node noch ein Kompilierungsschritt
ist erforderlich. Die native Ausführung prüft keine Typen: PutObjectCommandInput hilft
Ihrem Editor, Anfragefelder zu prüfen. Die Laufzeitprüfungen validieren weiterhin Argumente und
gespeicherte Ergebnisse.
Fazit
Verwenden Sie das ausgegebene JSON als Ergebnis eines abgeschlossenen Uploads samt Verifizierung und halten Sie stderr für die Fehlerdiagnose verfügbar. Wenn der Export ein Schritt in einem umfassenderen Workflow zur Dateiverarbeitung ist, entdecken Sie unsere Dienste.
