在Azure中如何将多个CloudBlockBlob合并为单个CloudBlockBlob对象
Azure块Blob合并最优实现方案
你遇到的超时和覆盖问题本质是没有使用块Blob原生的服务端拼接能力,无需将数据下载到函数内存即可完成多个CloudBlockBlob的合并,最终输出就是标准CloudBlockBlob类型,完全满足要求。
方案核心逻辑
Azure块Blob本身由多个可独立管理的块组成,你可以直接将每个源Blob作为目标块Blob的一个独立块提交,最后提交块列表即可完成服务端拼接,全程无数据下载到函数侧,性能极高不会触发超时。
- 你之前逐写会覆盖的原因是CloudBlockBlob的Upload系列方法默认是全量替换整个Blob内容,只有通过PutBlock + PutBlockList的方式才能逐步拼接内容,不会覆盖之前写入的块。
实现代码
public async Task CatBlob(string[] srcBlobs, string destinationBlob) { var connectionString = Config.AzConnStr; var container = Config.AzContainer; if (!CloudStorageAccount.TryParse(connectionString, out CloudStorageAccount storageAccount)) { Logger.Error("Exception connecting to cloud storage while concatenating files", Context); throw new Exception("Could not connect to the Azure using Connection String."); } try { CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(container); CloudBlockBlob blockBlobDest = cloudBlobContainer.GetBlockBlobReference(destinationBlob); List<string> blockIds = new List<string>(); for (int i = 0; i < srcBlobs.Length; i++) { CloudBlockBlob cloudBlockBlobSrc = cloudBlobContainer.GetBlockBlobReference(srcBlobs[i]); // 生成等长Base64编码的块ID,顺序和最终拼接顺序严格对应 string blockId = Convert.ToBase64String(BitConverter.GetBytes(i)); // 直接将源Blob内容作为块提交到目标Blob,服务端拷贝无需下载数据到本地 await blockBlobDest.PutBlockAsync(blockId, cloudBlockBlobSrc.Uri, null); blockIds.Add(blockId); } // 提交块列表,完成最终合并 await blockBlobDest.PutBlockListAsync(blockIds); } catch (Exception ex) { Logger.Error("Exception while concatenating files: " + ex.Message, Context); throw; } }
注意事项
- 单个块的最大支持大小为4GiB,如果你的源Blob超过该大小,需要先将源Blob拆分为多个块再提交
- 单个块Blob最多支持50000个块,如果你的源Blob数量超过5万,需要先分批合并为中间块Blob,再将中间块合并为最终Blob
- 如果源Blob和目标Blob不在同一个存储账户,给源Blob的URI添加SAS读取授权即可正常使用
内容的提问来源于stack exchange,提问作者PT2550
相关产品推荐
相关产品推荐

