Xamarin应用上传视频至Azure Blob Storage重试6次超时求解
问题成因
- 你配置的
BlobClientOptions.Retry.NetworkTimeout是Azure Storage SDK层面的单次请求超时阈值,但是SDK底层依赖的HttpClient默认超时时间为100秒(即报错中显示的0:01:40),旧版本SDK在Xamarin移动端环境下不会自动将你设置的NetworkTimeout同步到底层HttpClient.Timeout属性,因此单次请求时长超过100秒就会被底层HTTP客户端强制取消。 - 你当前使用
UploadAsync的无参重载上传大视频,SDK默认会优先尝试整文件单次PUT上传,不会自动启用分块传输。大文件整文件上传的单次请求持续时间很容易突破100秒阈值,且一旦请求失败需要重传整个文件,在移动端网络波动场景下出错概率极高。 - Xamarin各平台原生HTTP处理器(Android的
AndroidClientHandler、iOS的NSUrlSessionHandler)默认也存在100秒的单请求超时限制,未显式修改的情况下会拦截长耗时请求。
解决方法
- 显式配置底层HttpClient超时,穿透SDK的默认配置
不要仅依赖SDK内置的HTTP客户端初始化,手动传入自定义超时的HttpClient实例给SDK传输层,从最底层关闭超时限制:
// 初始化自定义HTTP客户端,设置无限超时 var httpClient = new HttpClient(); httpClient.Timeout = Timeout.InfiniteTimeSpan; BlobClientOptions blobClientOptions = new BlobClientOptions { // 传入自定义HTTP客户端作为传输实现 Transport = new HttpClientTransport(httpClient), Retry = { NetworkTimeout = Timeout.InfiniteTimeSpan, MaxRetries = 5, // 可根据场景调整重试次数,默认值为6 Delay = TimeSpan.FromSeconds(2), MaxDelay = TimeSpan.FromSeconds(10) } }; BlobClient blobClient = new BlobClient("你的连接字符串", "容器名", "目标Blob文件名", blobClientOptions);
- 强制启用分块上传,避免单请求耗时过长
大文件上传必须使用分块传输,将大文件拆分为小块并行/串行上传,单个块上传耗时极短,不会触发超时,且失败后仅需重传出错的块,无需重传整个文件。同时不要将整个视频文件全量读入内存转MemoryStream,直接使用文件流读取可以大幅降低内存占用,避免移动端OOM:
// 直接打开本地视频文件流,无需提前将整个文件读入字节数组 using var videoStream = File.OpenRead(本地视频文件的存储路径); var uploadOptions = new BlobUploadOptions { TransferOptions = new StorageTransferOptions { // 单个分块大小,移动端建议设置为1MB~4MB,此处设置为2MB MaximumTransferSize = 2 * 1024 * 1024, // 超过该阈值自动走分块上传,与分块大小保持一致即可 InitialTransferSize = 2 * 1024 * 1024, // 并发上传数,移动端建议设为2~3,避免占满带宽导致其他请求阻塞 MaximumConcurrency = 2 } }; await blobClient.UploadAsync(videoStream, uploadOptions);
- 平台特殊配置
- Android项目:若使用
AndroidClientHandler作为HTTP实现,确认项目配置中未手动设置全局请求超时拦截规则。 - iOS项目:如果需要支持应用退后台后继续上传,需要配置
NSUrlSession后台传输模式,否则应用退到后台后系统会自动暂停HTTP请求,超过阈值后会触发超时取消。
内容的提问来源于stack exchange,提问作者Ghyath Serhal
相关产品推荐
相关产品推荐

