首页 > 解决方案 > 如何在 Blazor 的 c# 中取消 BlockBlobClient 上传中间流?

问题描述

我正在使用 Blazor Webassembly 将文件上传到 Azure Blob 存储中的用户上传区域。

该代码工作正常,但我希望能够为用户提供取消选项(例如,在大量上传可能的几个文件时)。这是代码:

        public async Task<InfoBool> HandleFilesUpload(FileChangedEventArgs e, IProgress<Tuple<int, int, string>> progressHandler,
        IProgress<Tuple<int,string>> fileCountHandler, ExternalFileDTO fileTemplate, InfoBool isCancelling)
    {

        int FileCount =0;
        fileTemplate.CreatedBy = _userservice.CurrentUser;
        Tuple<int, string> reportfile;
        Tuple<int, int, string> CountProgressName;
        foreach (var file in e.Files)
        {
            FileCount++;
            reportfile = Tuple.Create(FileCount, file.Name);

            fileCountHandler.Report(reportfile);
            try
            {
                if (file == null)
                {
                    return new InfoBool(false, "File is null");

                }
                long filesize = file.Size;
                if (filesize > maxFileSize)
                {
                    return new InfoBool(false, "File exceeds Max Size");

                }
                fileTemplate.OriginalFileName = file.Name;

                var sendfile = await _azureservice.GetAzureUploadURLFile(fileTemplate);
                if (!sendfile.Status.Success) // There was an error so return the details
                {
                    return sendfile.Status;
                }
                CurrentFiles.Add(sendfile); // Add the returned sendfile object to the list
                BlockBlobClient blockBlobclient = new BlockBlobClient(sendfile.CloudURI);

                byte[] buffer = new byte[BufferSize];
                using (var bufferedStream = new BufferedStream(file.OpenReadStream(maxFileSize), BufferSize))
                {
                    int readCount = 0;
                    int bytesRead;
                    long TotalBytesSent = 0;
                    // track the current block number as the code iterates through the file
                    int blockNumber = 0;

                    // Create list to track blockIds, it will be needed after the loop
                    List<string> blockList = new List<string>();

                    while ((bytesRead = await bufferedStream.ReadAsync(buffer, 0, BufferSize)) > 0)
                    {
                        blockNumber++;
                        // set block ID as a string and convert it to Base64 which is the required format
                        string blockId = $"{blockNumber:0000000}";
                        string base64BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId));

                        Console.WriteLine($"Read:{readCount++} {bytesRead / (double)BufferSize} MB");

                        // Do work on the block of data
                        await blockBlobclient.StageBlockAsync(base64BlockId, new MemoryStream(buffer, 0, bytesRead));
                        // add the current blockId into our list
                        blockList.Add(base64BlockId);
                        TotalBytesSent += bytesRead;
                        int PercentageSent = (int)(TotalBytesSent * 100 / filesize);
                        CountProgressName = Tuple.Create(FileCount, PercentageSent, file.Name);
                        if (isCancelling.Success) //Used an InfoBool so its passed by reference
                        {
                            break; // The user has cancelled, so wind up.
                        }
                        progressHandler.Report(CountProgressName);
                    }
                    // add the blockList to the Azure which allows the resource to stick together the chunks
                    if (isCancelling.Success)
                    {
                        await blockBlobclient.DeleteIfExistsAsync(); // Delete the blob created
                    }
                    else
                    {
                        await blockBlobclient.CommitBlockListAsync(blockList);
                    }
                    // make sure to dispose the stream once your are done
                    bufferedStream.Dispose();   // Belt and braces
                }
                //
                // Now make a server API call to verify the file upload was successful
                //
                // Set the file status to the cancelling, cos the server can delete the file.
                sendfile.Status = isCancelling;
                await _azureservice.VerifyFileAsync(sendfile);

                if (isCancelling.Success)
                {
                    break;      // This breaks out of the foreach loop
                }

            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }
            finally
            {

            }
        }
        return new InfoBool(true, "All Ok");

服务器为上传创建一个 DB 记录,并在“GetAzureUploadURLFile”中返回一个 SAS 密钥,然后使用该密钥上传一个 blockblob 并提交。完成后,再次调用服务器告诉它客户端已完成上传。这允许服务器检查它是否存在并验证内容。

我设法通过我使用的名为 InfoBool 的通用类提供了一个指向 UI 线程的“isCancelling”链接,该类将通过引用传递。

在每个块之后调用进度处理程序,并轮询“InfoBool”。到目前为止,一切都很好。如果是取消,内循环中断,然后我需要整理。

当前显示的代码尝试仅删除 blockBlobClient 而不是提交它。这失败了一个例外,我想可能是因为它没有被提交,并在删除它之前尝试提交 blockblobClient,但结果相同。

我查看了文档,它提到了中止机制,但我看不到任何有关如何设置和使用它们的示例。有人知道如何中止我构建的块块客户端上传吗?非常感谢。

标签: c#azureazure-blob-storageblazor-webassembly

解决方案


推荐阅读