JavaScript客户端如何将请求响应流转换为Blob对象
响应流转Blob的正确实现方式
你之前的写法错误是因为ReadableStream是异步逐块传输的对象,不能直接同步转为Uint8Array,必须先完整读取所有流的二进制分块,汇总后才能生成Blob。
方案1:使用fetch内置blob()方法(推荐)
fetch的Response原生支持直接转为Blob,无需手动处理流读写,代码可大幅简化:
fetch('/api/load', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: src }) .then(response => { // 如需强制指定类型可以覆写,不需要的话直接返回response.blob()即可 return response.blob().then(rawBlob => new Blob([rawBlob], {type: 'image/jpeg'})) }) .then(blob => { // 这里拿到的就是处理完成的Blob对象 console.log('生成的Blob:', blob) })
方案2:手动处理流的实现(适用于自定义流操作场景)
如果你确实需要自行操作ReadableStream(比如实现加载进度监控、中途修改流数据),可以按以下两种方式实现:
方式A:基于你的现有代码改造
fetch('/api/load', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: src }) .then((response) => { const reader = response.body.getReader() // 存储所有二进制分块的数组 const chunks = [] return new ReadableStream({ start(controller) { return pump() function pump() { return reader.read().then(({ done, value }) => { if (done) { controller.close(); return; } // 读取到分块时先存入数组 chunks.push(value) controller.enqueue(value); return pump(); }) } } }).then(stream => { // 所有分块读取完成后直接生成Blob return new Blob(chunks, {type: 'image/jpeg'}) }) }) .then(blob => { // 拿到最终Blob对象 console.log('手动处理生成的Blob:', blob) })
方式B:更简洁的异步循环写法
如果不需要返回流做其他处理,直接收集分块生成Blob的写法更简单:
fetch('/api/load', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: src }) .then(async response => { const reader = response.body.getReader() const chunks = [] let done, value while (({ done, value } = await reader.read(), !done)) { chunks.push(value) } return new Blob(chunks, { type: 'image/jpeg' }) }) .then(blob => { // 处理Blob })
内容的提问来源于stack exchange,提问作者Grosu Cristi-Alexandru
相关产品推荐
相关产品推荐

