Ich arbeite auf einem Computer mit begrenztem Speicher und möchte eine dynamisch generierte Datei (nicht von der Festplatte) in Streaming-Weise auf S3 hochladen. Mit anderen Worten, ich kenne die Dateigröße nicht, wenn ich den Upload starte, aber ich werde sie am Ende wissen. Normalerweise hat eine PUT-Anforderung einen Content-Length-Header, aber vielleicht gibt es einen Weg, dies zu umgehen, z. B. die Verwendung eines mehrteiligen oder Chunked-Content-Typs.
S3 kann Streaming-Uploads unterstützen. Zum Beispiel hier:
http://blog.odonnell.nu/posts/streaming-uploads-s3-python-and-poster/
Meine Frage ist, kann ich dasselbe erreichen, ohne die Dateilänge zu Beginn des Uploads angeben zu müssen?
Antworten:
Sie müssen Ihre Datei in 5MiB + Chunks über die mehrteilige API von S3 hochladen . Jeder dieser Blöcke erfordert eine Inhaltslänge, aber Sie können vermeiden, große Datenmengen (100 MB +) in den Speicher zu laden.
S3 erlaubt bis zu 10.000 Teile. Wenn Sie also eine Teilegröße von 5 MB auswählen, können Sie dynamische Dateien mit bis zu 50 GB hochladen. Sollte für die meisten Anwendungsfälle ausreichen.
Allerdings: Wenn Sie mehr benötigen, müssen Sie Ihre Teilegröße erhöhen. Entweder durch Verwendung einer höheren Teilegröße (z. B. 10 MB) oder durch Erhöhen während des Uploads.
First 25 parts: 5MiB (total: 125MiB) Next 25 parts: 10MiB (total: 375MiB) Next 25 parts: 25MiB (total: 1GiB) Next 25 parts: 50MiB (total: 2.25GiB) After that: 100MiB
Auf diese Weise können Sie Dateien mit bis zu 1 TB hochladen (S3-Limit für eine einzelne Datei beträgt derzeit 5 TB), ohne unnötig Speicherplatz zu verschwenden.
Ein Hinweis zu Ihrem Link zum Sean O'Donnells-Blog :
Sein Problem unterscheidet sich von Ihrem - er kennt und verwendet die Inhaltslänge vor dem Hochladen. Er möchte diese Situation verbessern: Viele Bibliotheken verarbeiten Uploads, indem sie alle Daten aus einer Datei in den Speicher laden. Im Pseudocode wäre das ungefähr so:
data = File.read(file_name) request = new S3::PutFileRequest() request.setHeader('Content-Length', data.size) request.setBody(data) request.send()
Seine Lösung macht es, indem er das
Content-Length
über die Dateisystem-API erhält . Anschließend überträgt er die Daten von der Festplatte in den Anforderungsdatenstrom. Im Pseudocode:upload = new S3::PutFileRequestStream() upload.writeHeader('Content-Length', File.getSize(file_name)) upload.flushHeader() input = File.open(file_name, File::READONLY_FLAG) while (data = input.read()) input.write(data) end upload.flush() upload.close()
quelle
Setzen Sie diese Antwort hier für andere ein, falls es hilft:
Wenn Sie die Länge der Daten, die Sie auf S3 streamen, nicht kennen, können Sie mit
S3FileInfo
ihrerOpenWrite()
Methode beliebige Daten in S3 schreiben.var fileInfo = new S3FileInfo(amazonS3Client, "MyBucket", "streamed-file.txt"); using (var outputStream = fileInfo.OpenWrite()) { using (var streamWriter = new StreamWriter(outputStream)) { streamWriter.WriteLine("Hello world"); // You can do as many writes as you want here } }
quelle
Sie können das Befehlszeilentool gof3r verwenden, um nur Linux-Pipes zu streamen:
$ tar -czf - <my_dir/> | gof3r put --bucket <s3_bucket> --key <s3_object>
quelle
tar -czf - <my_dir/> | aws s3 --something-or-other
?Wenn Sie Node.js verwenden, können Sie ein Plugin wie s3-Streaming-Upload verwenden , um dies ganz einfach zu erreichen.
quelle
Weitere Informationen zu mehrteiligen HTTP-Enitity-Anforderungen. Sie können eine Datei als Datenblock an das Ziel senden.
quelle