2017-07-23 2 views
4

Ich möchte eine große Datei (mehrere GB) in einem AWS S3-Bucket aus einer ASP.NET Core Web API erstellen. Die Datei ist so groß, dass ich die Stream nicht in den Arbeitsspeicher laden möchte, bevor ich sie auf AWS S3 hochlade.Streamen Sie eine Datei mit mehreren GB von ASP.NET Core Web API nach AWS S3

Mit PutObjectAsync() Ich bin gezwungen, vorab füllen die Stream bevor sie auf die Weitergabe an die AWS SDK, unten dargestellt:

var putObjectRequest = new PutObjectRequest 
{ 
    BucketName = "my-s3-bucket", 
    Key = "my-file-name.txt", 
    InputStream = stream 
}; 
var putObjectResponse = await amazonS3Client.PutObjectAsync(putObjectRequest); 

Mein ideales Muster das AWS SDK würde bedeuten, eine StreamWriter (von möglichen Rückkehr) Ich konnte Write() zu vielen Malen und dann Finalise() wenn ich fertig bin.

Zwei Fragen bezüglich meiner Herausforderung:

  • Bin ich falsch informiert über die Stream vor PutObjectAsync() dem Aufruf auf vorab füllen zu müssen?
  • Wie soll ich meine große (Multi-GB-) Datei hochladen?

Antwort

1

Für solche Situationen AWS docs bietet zwei Optionen:

Hoch-Level-API einfach schlägt Ihnen eine TransferUtilityUploadRequest mit einem PartSize angegeben zu schaffen, so die Klasse selbst könnte die Datei hochladen, ohne dass Sie den Upload selbst durchführen müssen. In diesem Fall können Sie den Fortschritt des mehrteiligen Uploads mit dem Abonnement StreamTransferProgress erhalten. Sie können eine Datei, einen Stream oder ein Verzeichnis hochladen.

Low-level API, ist natürlich komplizierter, aber flexibler - Sie können den Upload initiieren, und danach laden Sie den nächsten Teil einer Datei in einer Schleife. Beispielcode aus Dokumentation:

var s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1); 

// List to store upload part responses. 
var uploadResponses = new List<UploadPartResponse>(); 

// 1. Initialize. 
var initiateRequest = new InitiateMultipartUploadRequest 
    { 
     BucketName = existingBucketName, 
     Key = keyName 
    }; 

var initResponse = s3Client.InitiateMultipartUpload(initRequest); 

// 2. Upload Parts. 
var contentLength = new FileInfo(filePath).Length; 
var partSize = 5242880; // 5 MB 

try 
{ 
    long filePosition = 0; 
    for (var i = 1; filePosition < contentLength; ++i) 
    { 
     // Create request to upload a part. 
     var uploadRequest = new UploadPartRequest 
      { 
       BucketName = existingBucketName, 
       Key = keyName, 
       UploadId = initResponse.UploadId, 
       PartNumber = i, 
       PartSize = partSize, 
       FilePosition = filePosition, 
       FilePath = filePath 
      }; 

     // Upload part and add response to our list. 
     uploadResponses.Add(s3Client.UploadPart(uploadRequest)); 

     filePosition += partSize; 
    } 

    // Step 3: complete. 
    var completeRequest = new CompleteMultipartUploadRequest 
     { 
      BucketName = existingBucketName, 
      Key = keyName, 
      UploadId = initResponse.UploadId, 
     }; 

    // add ETags for uploaded files 
    completeRequest.AddPartETags(uploadResponses); 

    var completeUploadResponse = s3Client.CompleteMultipartUpload(completeRequest);  
} 
catch (Exception exception) 
{ 
    Console.WriteLine("Exception occurred: {0}", exception.ToString()); 
    var abortMPURequest = new AbortMultipartUploadRequest 
     { 
      BucketName = existingBucketName, 
      Key = keyName, 
      UploadId = initResponse.UploadId 
     }; 
    s3Client.AbortMultipartUpload(abortMPURequest); 
} 

Asynchronous version of UploadPart ist auch vorhanden, so dass man diesen Weg untersuchen sollte, wenn Sie eine vollständige Kontrolle für Ihre Uploads benötigen.

+0

Gründe für den Downvote? – VMAtm

+0

Gibt es einen Link zwischen ** uploadResponses ** und ** completeRequest ** – Anjali

+0

ist es Beispielcode aus der Dokumentation. Soweit Sie sehen können, befindet sich der Link in 'initResponse.UploadId', Sie starten also den Upload, erhalten eine ID, laden alle Dateien hoch und beenden den Upload. – VMAtm

Verwandte Themen