ArrayBuffer转 文件流

这篇博客介绍了如何在JavaScript中处理二进制数据,特别是从ArrayBuffer转换为Base64,然后转为Blob,最终转换为文件流用于上传。过程中涉及axios库的使用,以及各种数据类型间的转换方法,如arrayBufferToBlob、base64ToFile和blobToFile等关键函数。

相关链接 - 流行因乐

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。

请求时 加入 arraybuffer 返回类型

      axios({
        method: 'get | post',
        url: "****",
        responseType: 'arraybuffer'
      }).then(res => {
        console.log(res);
        const blob = this.arrayBufferToBlob(res.data, sn);
        const file = this.blobToFile(blob, sn, format);
        this.upload(file);  // 执行业务流程 上传
      });

得到 ArrayBuffer类型,

转为 base64 后

	/** arrayBuffer 转 base64 */
    arrayBufferToBlob(arrayBuffer, filename) {
      return new Blob([arrayBuffer], { type: filename });
    },

再转为 blob

	/** base64 转 blob */
    base64ToFile(base64) {
      const arr = base64.split(",");
      const mime = arr[0].match(/:(.*?);/)[1];
      const suffix = mime.split("/")[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      const file = new File([u8arr], `${"file"}.${suffix}`, {
        type: mime,
      });

      return file;
    }

最后转为 文件流 (file)

	/** blob 转 文件流(file) */
    blobToFile(blob, filename, type) {
      return new File([blob], filename, { type })
    },
<think>好的,我现在需要解决用户的问题:如何将ArrayBuffer换为流。用户可能是在处理前端的数据流,比如处理文件上传或WebSocket传输中的数据。ArrayBufferJavaScript中用于表示二进制数据的对象,而流则是一种处理数据的抽象接口,特别是在处理大量数据时,流可以分块处理,减少内存占用。首先,我要回忆一下JavaScript中处理流的相关知识。在浏览器环境中,流API主要是ReadableStream,属于FetchAPI的一部分。要将ArrayBuffer换为流,需要创建一个ReadableStream实例,并在其中将ArrayBuffer的数据分块推送到流中。接下来,我需要确定换的具体步骤。ArrayBuffer是一个固定长度的二进制数据缓冲区,而流需要分块读取。因此,可能需要将ArrayBuffer分成多个较小的块,比如Uint8Array视图,然后逐块放入流中。或者,如果ArrayBuffer不大,也可以一次性将其放入流中,但这可能失去流分块处理的优势。然后,考虑如何将ArrayBuffer封装到ReadableStream中。ReadableStream的构造函数需要一个underlyingsource对象,该对象的start方法会接收controller参数,用于控制流的数据推送。在start方法中,可以通过controller.enqueue()方法将数据块加入流队列,最后调用controller.close()结束流。可能的实现方式是,将ArrayBuffer为Uint8Array视图,然后通过enqueue方法推送这个视图。这样,流中的每个块就是整个ArrayBuffer的数据。如果用户需要分块处理,比如将大文件分成多个部分传输,就需要手动将ArrayBuffer分割成多个较小的Uint8Array块,并逐一推送。例如,假设有一个ArrayBuffer,我们可以创建一个Uint8Array视图,然后将其作为流的一个数据块。代码可能如下:```javascriptfunctionarrayBufferToStream(arrayBuffer){returnnewReadableStream({start(controller){controller.enqueue(newUint8Array(arrayBuffer));controller.close();}});}```这段代码创建了一个ReadableStream,并在启动时立即将整个ArrayBuffer作为Uint8Array推送到流中,然后关闭流。这样,当流被消费时,会接收到整个数据块。但是,如果ArrayBuffer很大,分块传输可能更高效。这时候需要分割ArrayBuffer,例如每1024字节分一块:```javascriptfunctionarrayBufferToStream(arrayBuffer,chunkSize=1024){letoffset=0;returnnewReadableStream({pull(controller){constend=offset+chunkSize;constchunk=arrayBuffer.slice(offset,end);if(chunk.byteLength===0){controller.close();return;}controller.enqueue(newUint8Array(chunk));offset=end;}});}```这里使用pull方法,在每次需要数据时生成一个块。每次从当前offset位置切分chunkSize大小的块,直到处理完整个ArrayBuffer。这种方法适用于处理大文件,分块传输,避免一次性加载全部数据到内存。不过,可能需要注意ReadableStream的自动拉取机制。如果使用start方法一次性推送所有数据,可能更适合小数据;而使用pull方法可以在需要时生成数据块,适用于大数据或需要按需生成的情况。用户可能还需要了解如何将流换回ArrayBuffer。比如,使用Response对象或者通过读取流的所有块并合并:```javascriptasyncfunctionstreamToArrayBuffer(stream){constreader=stream.getReader();letchunks=[];lettotalLength=0;while(true){const{done,value}=awaitreader.read();if(done)break;chunks.push(value);totalLength+=value.length;}constbuffer=newUint8Array(totalLength);letoffset=0;for(constchunkofchunks){buffer.set(chunk,offset);offset+=chunk.length;}returnbuffer.buffer;}```这样可以将流中的数据收集到Uint8Array数组中,最后合并成一个ArrayBuffer。总结一下,用户的问题是将ArrayBuffer换为流,可能的实现方式有两种:一次性推送整个数据或分块推送。根据不同的使用场景选择合适的方案。此外,可能需要处理流的分块读取和合并,确保数据的正确传输。</think>将ArrayBuffer换为流可以通过创建`ReadableStream`实现。以下是使用JavaScript的两种实现方式: ### 方式一:完整数据一次性推送 ```javascript function arrayBufferToStream(arrayBuffer) { return new ReadableStream({ start(controller) { // 将整个ArrayBuffer为Uint8Array并推入流 controller.enqueue(new Uint8Array(arrayBuffer)); controller.close(); // 关闭流 } }); } ``` 此方式直接将整个ArrayBuffer作为单个数据块推送到流中,适用于小文件场景。 ### 方式二:分块推送(推荐大文件使用) ```javascript function arrayBufferToStream(arrayBuffer, chunkSize = 1024) { let offset = 0; // 当前读取位置 return new ReadableStream({ pull(controller) { // 计算当前分片的结束位置 const end = offset + chunkSize; // 切割ArrayBuffer获得分块 const chunk = arrayBuffer.slice(offset, end); if (chunk.byteLength === 0) { controller.close(); // 数据已全部发送 return; } // 推送当前分片 controller.enqueue(new Uint8Array(chunk)); offset = end; // 更新读取位置 } }); } ``` 此方式将ArrayBuffer按指定块大小分片传输,适用于大文件或需要实时处理的场景。 ### 使用示例 ```javascript // 创建测试数据 const buffer = new ArrayBuffer(1024); const view = new Uint8Array(buffer); view.forEach((_, i) => view[i] = i % 256); // 填充测试数据 // 创建流 const stream = arrayBufferToStream(buffer); // 读取流数据 const reader = stream.getReader(); reader.read().then(function process({ done, value }) { if (done) { console.log('Stream complete'); return; } console.log('Received chunk:', value); return reader.read().then(process); // 继续读取 }); ``` ### 反向操作:流ArrayBuffer ```javascript async function streamToArrayBuffer(stream) { const reader = stream.getReader(); const chunks = []; let totalLength = 0; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); // 收集数据块 totalLength += value.length; } // 合并所有分片 const combinedBuffer = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { combinedBuffer.set(chunk, offset); offset += chunk.length; } return combinedBuffer.buffer; // 返回ArrayBuffer } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值