1

Ich entwerfe eine Dateiupload-API, die mit großen Dateien arbeiten muss. Ich möchte mich von der Weitergabe von Byte-Arrays fernhalten. Der Endpunktspeicher für die Datei ist ein Drittanbieter wie Azure- oder Rackspace-Dateispeicher.ASP.NET Core - Hochladen von Dateistream und Puffer durch Geschäftsdomänenebenen

Ich habe die folgende Projektstruktur, die DDD Folgendes:

  1. Web API (Netcore - übernimmt die hochgeladene Datei)
  2. Business Service (Anrufe Azure die Datei zu speichern und speichert einen Datensatz die Datenbank)
  3. Domain (Domain-Modelle für EF)
  4. Persistenz (Repositorys EFCore - speichert die Datenbankänderungen)

Ich möchte Methoden in jedem haben, die den hochgeladenen Filestream starten können, sobald der Upload beginnt. Ich bin mir nicht sicher, ob das möglich ist.

Bisher haben wir byte [] verwendet, um die Dateien durch die Ebenen zu leiten, aber für große Dateien scheint dies viel Speicher zu erfordern und hat uns Probleme verursacht.

Ist es möglich, den Upload von Dateien über eine ältere Anwendung zu optimieren, so dass Sie keine großen Byte-Arrays kopieren müssen, und wenn ja, wie kann dies geschehen?

Um zu verdeutlichen, würde die Code-Struktur etwa so aussehen. Repository Sachen ausgeschlossen wurde:

namespace Project.Controllers 
{ 
    [Produces("application/json")] 
    [Route("api/{versionMNumber}/")] 
    public class DocumentController : Controller 
    { 
     private readonly IAddDocumentCommand addDocumentCommand; 

     public DocumentController(IAddDocumentCommand addDocumentCommand) 
     { 
      this.addDocumentCommand = addDocumentCommand; 
     } 

     [Microsoft.AspNetCore.Mvc.HttpPost("application/{applicationId}/documents", Name = "PostDocument")] 
     public IActionResult UploadDocument([FromRoute] string applicationId) 
     { 
      var addDocumentRequest = new AddDocumentRequest(); 
      addDocumentRequest.ApplicationId = applicationId; 
      addDocumentRequest.FileStream = this.Request.Body; 

      var result = new UploadDocumentResponse { DocumentId = this.addDocumentCommand.Execute(addDocumentRequest).DocumentId }; 

      return this.Ok(result); 
     } 
    } 
} 

namespace Project.BusinessProcess 
{ 
    public interface IAddDocumentCommand 
    { 
     AddDocumentResponse Execute(AddDocumentRequest request); 
    } 

    public class AddDocumentRequest 
    { 
     public string ApplicationId { get; set; } 
     public Stream FileStream { get; set; } 
    } 

    public class AddDocumentResponse 
    { 
     public Guid DocumentId { get; set; } 
    } 

    public class AddDocumentCommand : IAddDocumentCommand 
    { 
     private readonly IDocuentRepository documentRepository; 
     private readonly IMessageBus bus; 

     public AddDocumentCommand(IDocumentRepository documentRepository, IMessageBus bus) 
     { 
      this.documentRepository = documentRepository; 
      this.bus = bus; 
     } 

     public AddDocumentResponse Execute(AddDocumentRequest request) 
     { 
      /// We need the file to be streamed off somewhere else, fileshare, Azure, Rackspace etc 
      /// We need to save a record to the db that the file has been saved successfully 
      /// We need to trigger the background workers to process the uploaded file 

      var fileUri = AzureStorageProvider.Save(request.FileStream); 
      var documentId = documentRepository.Add(new Document { FileUri = fileUri }); 
      bus.AddMessage(new DocumentProcessingRequest { documentId = documentId, fileUri = fileUri }); 

      return new AddDocumentResponse { DocumentId = documentId }; 
     } 
    } 
} 
+0

brauchen und was Verarbeitung ist genau für diese Datei erforderlich? Wird bei dieser Verarbeitung diese Datei vollständig gelesen? – Evk

+0

@Evk nein, ich muss es nur übergeben, welche Dateispeicheranbieter wir verwenden. Zum Beispiel haben Rackspace Cloud-Dateien die Methode: 'cloudFiles.CreateObject (containerName, stream, fileUri);' und Azure Blob Storage hat die Methode 'blockBlob.UploadFromStream (fileStream);' – Junto

+0

Aber Sie sagten "aber die Datei muss zuerst in unserer Business-Schicht verarbeitet werden"? – Evk

Antwort

0

Einige Hinweise:

  1. Passing um ein Byte-Array oder Strom die Daten nicht kopiert werden - das Problem auf alle Daten auf dem Server haben. Wenn Ihr Webserver die Daten in seiner vollständigen Form verarbeiten muss, werden Sie nicht in der Lage sein, die Speichernutzung zu vermeiden.

  2. Wenn Sie die Daten auf Ihrem Webserver überhaupt nicht verarbeiten müssen, sondern nur in den BLOB-Speicher legen müssen, sollten Sie ein URI für den Upload zurückgeben, das auf BLOB-Speicher verweist (dies könnte sein hilfreich: Using CORS with Azure)

  3. Wenn Sie die Daten verarbeiten müssen, aber du bist in Ordnung zu tun, dass ein bisschen-at-a-time, so etwas wie diese Antwort ist, was Sie Using streams in ASP.Net web API