如何确保Azure Blob文件上传完成并获取上传进度?
确保Azure Blob上传完成及获取上传进度
一、确保上传操作彻底完成
你的代码中已经使用await blobClient.UploadAsync(...),理论上该方法会等待上传操作完全完成后才返回,但仍出现立即访问找不到的情况,可从以下几点排查解决:
1. 处理异地冗余存储的同步延迟
如果你的存储账户使用异地冗余存储(GRS/RA-GRS),次要区域的数据同步存在秒级延迟(极端情况可能更长)。若读取请求被路由到次要区域,就会出现上传完成但读取不到的情况。
解决办法:上传完成后主动验证Blob存在,必要时添加重试逻辑:
// 上传后主动确认Blob状态 var exists = await blobClient.ExistsAsync(); if (!exists) { // 循环重试3次,每次间隔1秒 for (int i = 0; i < 3; i++) { await Task.Delay(1000); exists = await blobClient.ExistsAsync(); if (exists) break; } } return exists;
2. 避免异步调用的同步阻塞问题
如果调用PutBlobAsync时使用Result或Wait()等同步阻塞方式,可能导致异步操作未真正完成就执行后续逻辑。必须始终用await调用该方法:
// 正确方式 var success = await PutBlobAsync("container", "blob", content); // 错误方式(可能导致上传未完成) var success = PutBlobAsync("container", "blob", content).Result;
3. 验证Blob名称一致性
Azure Blob存储对名称大小写不敏感但保留大小写,若后续访问时的Blob名称与上传时大小写不一致,可能出现找不到的情况。确保前后使用的blobName完全一致。
二、获取上传进度状态
可以通过BlobUploadOptions的ProgressHandler属性实现上传进度跟踪,修改后的代码如下:
public async Task<bool> PutBlobAsync(string containerName, string blobName, byte[] content, bool allowOverwrite = false, string contentType = null, IProgress<long> progress = null) { try { var containerClient = CreateAndGetContainer(containerName); var blobClient = containerClient.GetBlobClient(blobName); var blobUploadOptions = new BlobUploadOptions(); if (!String.IsNullOrEmpty(contentType)) blobUploadOptions.HttpHeaders = new BlobHttpHeaders { ContentType = contentType }; if (!allowOverwrite) blobUploadOptions.Conditions = new BlobRequestConditions { IfNoneMatch = ETag.All }; // 设置进度回调 if (progress != null) { blobUploadOptions.ProgressHandler = new Progress<long>(bytesTransferred => { progress.Report(bytesTransferred); }); } // 直接用content初始化MemoryStream,简化代码 using (var stream = new MemoryStream(content)) { await blobClient.UploadAsync(stream, blobUploadOptions); } // 主动确认Blob存在 var exists = await blobClient.ExistsAsync(); if (!exists) { for (int i = 0; i < 3; i++) { await Task.Delay(1000); exists = await blobClient.ExistsAsync(); if (exists) break; } } return exists; } catch (RequestFailedException e) { Logger.Error(e, "PutBlobAsync"); switch (e.Status) { case (int)HttpStatusCode.NotFound: case (int)HttpStatusCode.PreconditionFailed: return false; } throw; } }
调用时传入进度跟踪实例即可实时获取进度:
var progress = new Progress<long>(bytes => { Console.WriteLine($"已上传 {bytes} 字节,总大小 {content.Length} 字节"); }); var success = await PutBlobAsync("my-container", "my-blob.txt", content, false, "text/plain", progress);
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

