使用TransferManager进行服务器端复制时如何覆盖Blob
服务端复制Blob时无法覆盖的解决方法
问题根源
使用TransferManager的ServiceSideSyncCopy模式时,TransferContext.ShouldOverwriteCallbackAsync = TransferContext.ForceOverwrite的逻辑不适用——服务端复制依赖Azure存储原生的Copy Blob API,客户端的覆盖回调无法触发服务端的覆盖规则,直接设置会导致"Blob operation is not supported"异常。而客户端复制(SyncCopy)是本地下载再上传,所以回调逻辑能正常工作。
可行解决方案
方案1:先删后复制
在执行服务端复制前,手动检查目标Blob是否存在,若需要覆盖则先删除:
var sourceFile = this.sourceContainerManagement .GetCloudBlobClient() .GetContainerReference(sourceContainer) .GetBlockBlobReference(source); var destinationFile = this.destinationContainerManagement .GetCloudBlobClient() .GetContainerReference(destinationContainer) .GetBlockBlobReference(destination); var transferContext = new SingleTransferContext(); if (forceOverwrite) { // 检查目标Blob存在则删除 if (await destinationFile.ExistsAsync()) { await destinationFile.DeleteAsync(); } } await TransferManager.CopyAsync( sourceFile, destinationFile, clientSideCopy ? CopyMethod.SyncCopy : CopyMethod.ServiceSideSyncCopy, new CopyOptions(), transferContext);
方案2:通过CopyOptions设置访问条件
利用CopyOptions的访问条件参数,直接告诉Azure存储服务允许覆盖已存在的Blob:
var sourceFile = this.sourceContainerManagement .GetCloudBlobClient() .GetContainerReference(sourceContainer) .GetBlockBlobReference(source); var destinationFile = this.destinationContainerManagement .GetCloudBlobClient() .GetContainerReference(destinationContainer) .GetBlockBlobReference(destination); var transferContext = new SingleTransferContext(); var copyOptions = new CopyOptions(); if (forceOverwrite) { // 设置访问条件:允许覆盖任何已存在的目标Blob copyOptions.ModifyAccessCondition = new AccessCondition { IfMatch = AccessCondition.GenerateIfMatchCondition("*") }; } await TransferManager.CopyAsync( sourceFile, destinationFile, clientSideCopy ? CopyMethod.SyncCopy : CopyMethod.ServiceSideSyncCopy, copyOptions, transferContext);
补充说明
- 方案1逻辑简单,适合小文件或目标Blob存在概率不高的场景;
- 方案2更贴合服务端复制的原生逻辑,避免额外的删除请求,效率更高。
内容的提问来源于stack exchange,提问作者shubham
相关产品推荐
相关产品推荐

