问题描述在两个 Azure Storage Account 之间复制大文件时最常见的担心是如果要复制 1 TB、10 TB甚至更多 Blob 数据会不会像普通网络传输一样产生大量流量费用这个问题不能只看“源账号”和“目标账号”是不是不同账号而要先看复制方式。如果应用程序先把 Blob 下载到本地、VM、容器或 App Service再上传到另一个 Storage Account那么数据确实会经过应用所在网络网络带宽、出站流量、NAT、防火墙或私有网络组件都可能参与计费和限流。Azure Storage 其实还提供了另一种方式服务器端复制Server-Side Copy对应Copy Blob、Put Blob From URL、Put Block From URL这几个 API。看起来像是在服务端完成复制但它到底是不是真的不经过我的应用网络用它在两个 Storage Account 之间搬 1 TB、10 TB 数据时会不会还是产生大量流量费用这就是本文要回答的问题。问题解答如果使用 Azure Storage 服务器端复制Blob 的大块数据不会经过你的应用服务器或自建网络链路。应用程序发出去的主要是一个复制请求真正的数据搬运发生在 Azure Storage 服务后端。所以两个 Storage Account 之间复制 Blob 时真正要避免的是“下载再上传”这种写法。只要源 Blob 能被目标 Storage 授权读取目标 Storage 就可以直接从源 URL 拉取数据并写入目标 Blob。应用不需要读取 Blob 内容也不需要把 1 TB 数据重新上传一遍。1. 先区分两种复制方式复制方式数据路径是否容易产生大量应用侧流量应用下载源 Blob再上传到目标账号Source Storage → 应用 → Destination Storage是Storage 服务器端复制Source Storage → Azure Storage 后端 → Destination Storage否把这两条路径画成图更直观这里的重点是应用程序只参与“发起复制”不参与“搬运内容”。因此大文件 payload 不会压到应用服务器、NAT、代理、防火墙或私有网络链路上。2. 费用边界不是“完全免费”而是“不走应用网络”这里要避免一个过度简化的说法服务器端复制不等于所有费用都没有。评估这类需求时第一步不是写代码而是先确认源和目标是不是都在 Azure Blob Storage、是不是同一个区域——这两点基本决定了费用结构。更准确的理解是场景费用理解同区域 Storage Account 之间服务器端复制大文件数据不经过应用网络通常不产生互联网出站流量费用但仍有 Storage 事务费用跨区域 Storage Account 之间复制数据仍不经过应用网络但需要评估跨区域数据传输费用应用下载再上传数据经过应用网络可能产生明显带宽、出站、NAT、防火墙或私有链路相关费用建议只要不需要在复制过程中处理文件内容优先使用服务器端复制而不是自己写下载再上传。3. .NET 里怎么选 API常见选择可以压缩成一张表场景推荐 API大小限制中小 Blob希望同步完成SyncUploadFromUriAsync源 Blob ≤ 5,000 MiB对应Put Blob From URL大文件复制接受异步状态轮询StartCopyFromUriAsync异步Copy Blob无大小上限超大文件需要分块、重试、进度控制StageBlockFromUriAsyncCommitBlockListAsync每块最大 4,000 MiB对应Put Block From URL需 API 版本 2019-12-12大多数跨账号大文件复制先选StartCopyFromUriAsyncCopyFromUriOperation operation await destinationBlob.StartCopyFromUriAsync(sourceSasUri); await operation.WaitForCompletionAsync();这里的sourceSasUri只需要让目标 Storage 能读取源 Blob。生产环境里不建议使用账号 Key 生成长期 SAS更推荐使用托管身份访问目标账号并使用短有效期 User Delegation SAS 授权源 Blob 读取。4. 常见报错403 CannotVerifyCopySource当源账号启用了防火墙或网络规则时服务器端复制可能会遇到这个报错403 This request is not authorized to perform this operation. CannotVerifyCopySource这个错误不一定是 SAS 过期也不一定是 RBAC 角色缺失。它经常表示目标 Storage 服务在验证或读取源 Blob 时被源账号的网络规则挡住了。这里的关键点是复制请求虽然是你从应用程序发起的但真正读取源 Blob 的动作发生在 Storage 服务后端如果源账号没有给这条服务端读取路径放行目标端就无法验证源。一般按下面顺序排查检查点重点看什么常见处理源 URL 授权SAS 是否有r权限是否过期时间是否受时钟偏差影响使用短有效期 User Delegation SAS开始时间可以略早几分钟目标账号权限发起复制的身份是否能写目标容器给托管身份分配Storage Blob Data Contributor源账号网络规则源账号是否允许目标 Storage 后端读取源 Blob评估网络例外、Trusted Microsoft services 或 Resource instance ruleCopy scope目标账号是否限制了允许的复制来源检查AllowedCopyScope例如是否限制为同租户或 PrivateLinkDNS 与 Private Endpoint应用访问源、目标账号时是否解析到预期私有地址检查privatelink.blob.core.windows.net私有 DNS 区域和 VNet link这里不要把“客户端能访问源账号”直接等价成“目标 Storage 后端也能读取源账号”。两者不是同一条路径。即使应用能访问源账号和目标账号也不自动代表 Storage 服务端复制一定满足源账号的网络限制。参考资料Copy a blob with .NETCopy Blob REST APIPut Blob From URL REST APIPut Block From URL REST APITroubleshoot 403 errors in Azure Blob StorageUse AzCopy to copy blobs between Azure storage accounts with network restrictionsRestrict the source of copy operations to a storage account