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:
- Web API (Netcore - übernimmt die hochgeladene Datei)
- Business Service (Anrufe Azure die Datei zu speichern und speichert einen Datensatz die Datenbank)
- Domain (Domain-Modelle für EF)
- 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 };
}
}
}
brauchen und was Verarbeitung ist genau für diese Datei erforderlich? Wird bei dieser Verarbeitung diese Datei vollständig gelesen? – Evk
@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
Aber Sie sagten "aber die Datei muss zuerst in unserer Business-Schicht verarbeitet werden"? – Evk