React JS调用Azure存储Blob下载文件时readableStreamBody为undefined问题
React从Azure存储下载文件时readableStreamBody为undefined的解决方法
核心问题排查与修复
首先,你的代码中BlobServiceClient的初始化URL格式错误,这是导致readableStreamBody为undefined的常见原因:
SAS令牌是URL查询参数,必须以?开头拼接在存储账户URL后,而不是直接附加。错误的拼接会导致SDK无法正确解析认证信息,即使看似能访问存储,实际返回的响应结构也会异常。
修正后的初始化代码:
const storageAccount = '<storage-account-name>'; const sas = '<sas-token>'; // 关键:添加?将SAS作为查询参数 const blobService = new BlobServiceClient( `https://${storageAccount}.blob.core.windows.net/?${sas}` );
其他必要检查项
验证SAS令牌权限
确保你的SAS令牌包含读取(r)权限——下载Blob必须具备该权限。如果SAS仅配置了写入或其他权限,下载请求会静默失败,无法返回有效流。确认目标Blob存在
在下载前先验证Blob是否存在,避免因Blob不存在导致的无流返回:
const exists = await blobClient.exists(); if (!exists) { console.error('目标Blob不存在'); return; }
- 适配SDK版本的流属性
部分新版本的@azure/storage-blob中,可读流的属性名从readableStreamBody改为了body。可以兼容两种写法:
const downloadResponse = await blobClient.download(); const readableStream = downloadResponse.readableStreamBody || downloadResponse.body;
Azure存储账户配置检查
如果以上代码调整后仍有问题,需要检查存储账户的网络与CORS设置:
- 网络访问规则:如果存储账户开启了防火墙,需将React应用的客户端IP(开发环境通常是本地IP)加入允许列表,或者临时设置为“允许所有网络访问”用于测试。
- CORS配置:在Azure门户的存储账户→Blob服务→CORS中,添加规则:
- 允许的来源:填入React应用的域名(如
http://localhost:3000) - 允许的方法:勾选
GET - 允许的标头/公开的标头:设为
* - 最大年龄:3600
- 允许的来源:填入React应用的域名(如
完整下载示例
整合以上修复后的完整代码:
const storageAccount = '<storage-account-name>'; const sas = '<sas-token>'; const containerName = '<container-name>'; const fileName = '<file-name>'; const blobService = new BlobServiceClient( `https://${storageAccount}.blob.core.windows.net/?${sas}` ); async function downloadBlobToLocal() { try { const containerClient = blobService.getContainerClient(containerName); const blobClient = containerClient.getBlockBlobClient(fileName); const exists = await blobClient.exists(); if (!exists) { throw new Error('目标Blob不存在'); } const downloadResponse = await blobClient.download(); const readableStream = downloadResponse.readableStreamBody || downloadResponse.body; if (!readableStream) { throw new Error('无法获取Blob可读流'); } // 将流转换为Blob并触发浏览器下载 const blob = await new Response(readableStream).blob(); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = fileName; document.body.appendChild(link); link.click(); // 清理资源 window.URL.revokeObjectURL(url); document.body.removeChild(link); } catch (error) { console.error('下载失败:', error.message); } } // 调用下载函数 downloadBlobToLocal();
内容的提问来源于stack exchange,提问作者Hisham
相关产品推荐
相关产品推荐

