c# - 如何在 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,但结果相同。
我查看了文档,它提到了中止机制,但我看不到任何有关如何设置和使用它们的示例。有人知道如何中止我构建的块块客户端上传吗?非常感谢。
解决方案
推荐阅读
- python - 这算作多少次写入?[火库]
- sql-server - SQL Server SCALAR FUNCTION 中 ')' 附近的语法不正确
- python - Pandas - 将 df.apply() 的结果存储为仅选择行
- automation - 在空手道中启用特定于功能的属性
- php - 带有 Laravel 的 PayPal API - 更新数据
- python - 根据 pandas 中的组为列分配值
- amazon-web-services - 访问另一个 ec2 实例上的应用程序
- python - 将 dtype('int64') 转换为 pandas 数据框
- ruby - 是否可以访问类之外的受保护方法 - ruby
- angular - Angular Universal 不渲染