Azure Blob下载时progress事件仅触发一次 如何获取实时下载进度
Azure Blob 下载progress事件仅触发100%完成态的修复方案
问题原因
你当前代码拿不到实时进度是几个问题叠加导致的:
- 你用的v2版
azure-storageSDK的getBlobToStream方法,默认的进度采样间隔是动态计算的,对于你这种只有4.61KB的小文件,默认采样间隔比文件总下载时长还长,只会在下载完成时触发一次progress事件 - 你当前是先调用下载方法、拿到返回的speedSummary对象后才绑定progress监听器,存在时序差,下载启动初期触发的进度事件会因为没有挂载监听器直接丢失
- 原有代码没补全非403错误的reject逻辑,网络异常时会出现Promise挂死的问题
修复方案
按下面核心点调整即可:
- 给
getBlobToStream传入显式配置,把进度采样间隔设为固定小值(比如50ms),强制SDK按固定频率抛进度事件 - 拿到方法返回的speedSummary对象后立刻绑定progress事件,不要加额外的同步逻辑延迟绑定
- 补全错误分支的Promise状态流转,避免挂死
调整后的代码如下:
async function getBackupTemplate(shipKey, historyLogBlobDirectory, reportDataBlobDirectory) { const historyLogStreamPath = `${window.remote.app.getPath('userData')}/backupStream1.txt`; const reportDataStreamPath = `${window.remote.app.getPath('userData')}/backupStream2.txt`; const historyLog = await new Promise((resolve, reject) => { const stream = fs.createWriteStream(historyLogStreamPath); // 配置下载参数,核心是设置固定进度采样间隔 const downloadOptions = { speedSummary: { // 每50ms触发一次进度回调,小文件可以设到20ms保证能拿到中间进度 triggerInterval: 50 } }; // 调用下载方法,传入配置 const historySummary = window.blobService.getBlobToStream( window.containerName, historyLogBlobDirectory, stream, downloadOptions, async (err, text) => { console.log(historyLogStreamPath) console.log('historySummary1', historySummary) if (err) { if (err.statusCode === 403) { azureCustomService.setRequestDateHeaderFromAzureServerTimeStamp(err.message); await azureCustomService.communicateAzureWithCustomHeader('GET', window.containerName, historyLogBlobDirectory); azureCustomService.streamParsingToJSON(historyLogStreamPath, (parseErr, data) => { if (parseErr) return reject(parseErr); resolve(JSON.parse(data)); }); } else { // 补全其他错误的reject,避免Promise挂死 reject(err); } } else { console.log('comp history', text) azureCustomService.streamParsingToJSON(historyLogStreamPath, (parseErr, data) => { if (parseErr) return reject(parseErr); resolve(JSON.parse(data)); }); } } ); // 立刻绑定进度事件,不要延迟 historySummary.on('progress', function() { const percentComplete = historySummary.getCompletePercent(2); const totalSize = historySummary.getTotalSize(true); const downloadedSize = historySummary.getCompleteSize(true); // 这里可以把进度同步给UI层做实时展示 console.log(`下载进度:${percentComplete}%`); console.log(`已下载:${downloadedSize} / 总大小:${totalSize}`); }); console.log('historySummary2', historySummary) }); // 后续reportData的下载逻辑可以复用同样的配置和事件绑定方式 return { historyLog }; }
补充说明
- 如果下载的文件体积极小(几KB级别),即使采样间隔设到20ms,也可能因为本地环回/内网下载速度过快只触发1-2次进度事件,属于正常现象,可以在UI层加简单的进度平滑动画优化体验
- 如果后续升级到v12+版本的
@azure/storage-blobSDK,进度获取逻辑变更为在download方法的onProgress回调中直接返回已下载字节数,不需要再依赖speedSummary对象
内容的提问来源于stack exchange,提问作者June
相关产品推荐
相关产品推荐

