【问题标题】:How to upload large files to Azure blob storage in background and responding 202 accepted right away?如何在后台将大文件上传到 Azure blob 存储并立即响应 202?
【发布时间】:2023-01-19 21:08:40
【问题描述】:

我有一个文件上传 webapi 端点,它接受 IFormFile 。我想将 100Mbs 到 GBs 的大文件上传到 Azure blob 存储。我想在后台上传文件,并在看到文件长度大于某个阈值后立即返回 202 accepted。

我有以下控制器和注入的服务代码:

    [HttpPost]
    public async Task<IActionResult> UploadFilesAsync(IFormFile uploadedFile, CancellationToken cancellationToken = default)
    {
        // some other code . . . . 

        if (uploadedFile.Length > _appConfig.Value.Threshold)
             result = await _fileService.UploadFileAsync(uploadedFile, fileDataType, cancellationToken);
             
        //map result and more code . . .
        return CreatedAtRoute(nameof(GetFileAsync), new { fileId = result.FileId }, mappedDto);

    }
    
    public async Task<FileUploadResult> UploadFileAsync(IFormFile uploadedFile,CancellationToken cancellationToken)
    {
        var fileUploadResult = new fileUploadResult( . . .)
    
        _ = System.Threading.Tasks.Task.Run(async () =>
        {
            var processResult = await _blobStorage.SaveFileAsync(uploadedFile,cancellationToken);

            // upload is completed, update FileEntity status
            var processStatus = processResult.HasError ? ProcessStatus.Failed : ProcessStatus.Succeeded;
            await _fileRepository.UpdateFileEntityAsync(blobFileInfo, processStatus, cancellationToken);
        }, cancellationToken);

        return fileUploadResult ;
    }

我试过 Task.Run 但我仍然注意到在使用邮递员上传时 api 仍然挂起,我还了解到不推荐 Task.Run。我可以在 .net6 中使用什么来触发后台上传过程并响应 202Accepted ?

【问题讨论】:

    标签: c# asp.net-core task .net-6.0


    【解决方案1】:

    有几种方法可以在后台将大文件上传到 Azure Blob 存储,同时立即响应 202 已接受状态。一种方法是使用 Azure Functions 和 Azure Queue Storage 异步处理文件上传。以下是如何实现此功能的概述:

    创建一个用于侦听 HTTP 触发器的 Azure 函数。此函数将负责接收文件上传并将消息添加到 Azure 队列存储。

    在函数中,验证文件并立即响应 202 Accepted 状态。

    验证后,将包含文件详细信息(例如文件名、文件大小等)的消息添加到 Azure 队列存储

    创建另一个 Azure Functions 来侦听来自 Azure 队列存储的消息。此函数将负责将文件上传到 Azure Blob 存储。

    在此函数中,检查队列中是否有新消息,如果找到消息,则使用 Azure Blob Storage SDK 将文件上传到 Azure Blob Storage。

    文件上传后,从队列中删除消息,记录文件信息(如文件名、文件大小、上传时间)

    以下是如何在 Azure 函数中处理文件上传的示例:

    [FunctionName("UploadFile")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        // Validate the file and return a 202 Accepted status
        var file = req.Form.Files[0];
        if (file.Length == 0)
        {
            return new AcceptedResult();
        }
        
        // Add a message to the Azure Queue Storage
        var message = new CloudQueueMessage(file.FileName);
        await queue.AddMessageAsync(message);
    
        return new AcceptedResult();
    }
    

    下面是一个示例,说明如何使用 Azure Blob 存储 SDK 在另一个 Azure 函数中处理文件上传:

    [FunctionName("ProcessFile")]
    public static async Task Run([QueueTrigger("file-upload-queue")]string fileName, ILogger log)
    {
        // Use the Azure Blob Storage SDK to upload the file
        var blockBlob = container.GetBlockBlobReference(fileName);
        using (var fileStream = System.IO.File.OpenRead(fileName))
        {
            await blockBlob.UploadFromStreamAsync(fileStream);
        }
    
        // Delete the message from the queue and log the file information
        await queue.DeleteMessageAsync(message);
        log.LogInformation($"File uploaded: {fileName}");
    }
    

    请务必注意,在这种方法中,您将消耗额外的存储空间和性能,因为文件在上传到 Azure Blob 存储时需要存储在 Azure 队列存储中。另一种使用 Azure Blob Storage SDK 的方法是使用 PutBlockAsync 方法并使用 PutBlockListAsync 更新阻止列表,这允许您分块上传文件,这样您可以立即响应 202 已接受状态,但它需要一些额外的代码处理块并在 Azure Blob 存储上重新组合文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-18
      • 2021-12-18
      • 2019-08-13
      • 2015-06-16
      • 2017-01-24
      • 2017-08-19
      • 2019-07-10
      相关资源
      最近更新 更多