ASP.NET Core - 通过业务域层上传文件流和缓冲区

Posted

技术标签:

【中文标题】ASP.NET Core - 通过业务域层上传文件流和缓冲区【英文标题】:ASP.NET Core - Upload file stream and buffer through business domain layers 【发布时间】:2018-05-28 13:12:36 【问题描述】:

我正在设计一个需要处理大文件的文件上传 API。我想远离传递字节数组。文件的端点存储将是第三方,例如 Azure 或 Rackspace 文件存储。

我有以下项目结构,遵循 DDD:

    Web API(Netcore - 接受上传的文件) 业务服务(调用 Azure 以保存文件并将记录保存到数据库) 域(EF 域模型) 持久性(存储库 EFCore - 保存数据库更改)

我希望在每个方法中都有可以在上传开始后立即开始通过上传文件流的方法。我不确定这是否可能?

之前我们使用 byte[] 将文件通过层传递,但对于大文件,这似乎需要大量内存来执行此操作并给我们带来了问题。

是否可以通过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 ;
        
    

【问题讨论】:

这个文件究竟需要什么处理?此处理是否涉及完全读取该文件? @Evk 不,我只需要将它传递给我们使用的任何文件存储提供商。例如,Rackspace Cloud 文件有方法:'cloudFiles.CreateObject(containerName, stream, fileUri);'和 Azure Blob 存储有方法 'blockBlob.UploadFromStream(fileStream);' 但是你说“但是文件需要先在我们的业务层进行一些处理”? 编辑后我仍然不清楚问题是什么。您可以在示例中的层之间传递Stream,就像您想要的那样。它没有按您的预期工作还是什么? 基本上你需要流式传输文件,尽管我认为这确实限制了你可以做些什么来“处理”它。这里有一些信息docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads 【参考方案1】:

一些注意事项:

    传递字节数组或流不会复制数据 - 问题在于您的服务器上根本没有数据。如果您的网络服务器需要处理完整形式的数据,您将无法避免这样做的内存使用。

    1234563乐于助人:Using CORS with Azure)

    如果您需要处理数据,但您可以一次一点地处理,那么您就需要像这样的答案Using streams in ASP.Net web API

【讨论】:

以上是关于ASP.NET Core - 通过业务域层上传文件流和缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core MVC(C#) 文件上传及后台输出响应Aspose.Words处理后文件

使用 Azure 媒体服务和 Asp.Net Core 上传和管理媒体文件的最佳方式

ASP.NET Core —上传.json文件并转换为List

asp.net core 通过ajax上传图片及wangEditor图片上传

ASP.NET Core 文件上传 之 文件签名验证

在ASP.NET Core 中上传文件