2017-12-14 28 views
1

대용량 파일을 사용해야하는 파일 업로드 API를 설계하고 있습니다. 나는 바이트 배열을 돌아 다니지 않기를 원한다. 파일의 끝점 저장소는 Azure 또는 Rackspace 파일 저장소와 같은 타사입니다.ASP.NET 코어 - 비즈니스 도메인 계층을 통해 파일 스트림 및 버퍼 업로드

나는 DDD 따르고 다음 프로젝트 구조, 한 :

  1. 웹 API - 파일을 저장 하늘빛에
  2. 비즈니스 서비스 (통화 (Netcore는 업로드 된 파일을 받아)와에 기록을 저장 데이터베이스)
  3. 도메인 (EF의 도메인 모델)
  4. 지속성 (저장소 EFCore이 - 데이터베이스 변경 사항을 저장)

나는 업로드가 시작 되 자마자 업로드 된 파일 스트림을 통과 할 수있는 각각의 메소드를 갖고 싶습니다. 가능하다면 확신 할 수 없나요?

이전에는 바이트 []를 사용하여 레이어를 통해 파일을 전달했지만 대용량 파일의 경우 많은 메모리가 필요하여 문제가 발생했습니다.

ntier 응용 프로그램을 통해 파일 업로드를 최적화 할 수 있으므로 큰 바이트 배열을 복사 할 필요가 없으며, 그렇다면 어떻게 할 수 있습니까?

명확히하기 위해 코드 구조는 다음과 같습니다. 저장소 물건은 제외되었습니다

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

그리고 무엇을 필요이라고하고 괜찮 경우

  • 이 파일에는 정확히 처리가 필요합니까? 이 처리 과정에서 해당 파일을 완전히 읽는 작업이 포함되어 있습니까? – Evk

  • +0

    @Evk no, 필자는 우리가 사용하는 파일 저장 프로 바이더를 어느 정도까지 전달해야합니다. 예를 들어, Rackspace Cloud 파일에는 'cloudFiles.CreateObject (containerName, stream, fileUri);'메소드가 있습니다. Azure Blob Storage에는 'blockBlob.UploadFromStream (fileStream);'메서드가 있습니다. – Junto

    +0

    하지만 당신은 "파일은 먼저 비즈니스 계층에서 약간의 프로세싱이 필요합니다"라고 말했습니까? – Evk

    답변

    0

    일부 노트 : 데이터를 복사하지 않습니다 바이트 배열 또는 스트림 주위에 전달

    1. 을 - 문제가 모든 서버에있는 데이터를 가지고있다. 웹 서버가 완전한 형식으로 데이터를 처리해야하는 경우 메모리 사용을 피할 수 없습니다.

    2. 웹 서버에서 데이터를 처리 할 필요가 없지만 BLOB 저장소에 저장해야하는 경우 BLOB 저장소를 가리키는 업로드 URL을 반환해야합니다. 도움 : Using CORS with Azure)는 데이터를 처리해야하지만 당신은이 비트에-A-시간이 대답 같은 것을 당신이 Using streams in ASP.Net web API