bricks/docs/cn.old/binstreaming.md
2025-11-19 12:30:39 +08:00

6.0 KiB
Raw Blame History

Bricks 流媒体传输模块技术文档


概述

bricks.UpStreamingbricks.down_streaming 是用于实现浏览器端流式数据上传与下载的 JavaScript 工具类,基于现代 Web APIReadableStreamfetch)构建。该模块适用于需要实时上传二进制数据(如音频、视频流)或处理响应流的场景。

主要功能包括:

  • 上行流UpStreaming:通过 POST 请求将数据以 application/octet-stream 格式分块发送至指定 URL。
  • 下行流解析器down_streaming:异步生成器函数,用于消费 Response.body 的流式内容,并将其转换为字符串输出。

依赖说明

本模块依赖以下现代浏览器特性:

  • ReadableStream
  • Headers
  • fetch() API支持 duplex: 'full'
  • async/awaitasync generator 函数
  • TextDecoder(隐含在 String.fromCharCode 使用中)

⚠️ 注意:duplex: 'full' 是处理流式请求所必需的,目前仅在部分现代浏览器(如 Chrome 105+)中支持。


命名空间初始化

bricks = window.bricks || {};

确保 bricks 全局命名空间存在,避免覆盖已有定义。


类:bricks.UpStreaming

继承自 bricks.JsWidget,提供流式上传能力。

继承关系

class UpStreaming extends bricks.JsWidget

需确保 bricks.JsWidget 已正确定义并可用。


构造函数

constructor(opts)

参数

参数 类型 描述
opts Object 配置对象,必须包含 url 字段

示例配置:

{
  url: "https://example.com/upload"
}

实现逻辑

调用父类构造函数 super(opts),初始化组件基础属性。


方法

async go()

启动流式上传请求。

返回值
  • {Promise<Response>}:返回一个 resolve 为 Response 对象的 Promise。
实现细节
  1. 创建一个可读流 this.body使用当前实例作为其源source
  2. 设置请求头:
    • Content-Type: application/octet-stream
  3. 使用 fetch 发起 POST 请求:
    fetch(this.url, {
      method: 'POST',
      headers: this.headers,
      duplex: 'full',
      body: this.body
    })
    
  4. 返回响应 Response 对象。

💡 duplex: 'full' 表示客户端可以同时写入请求体并读取响应,常用于流式接口。


send(data)

向流中写入一段数据。

参数
参数 类型 描述
data ArrayBuffer / Uint8Array 等 要发送的二进制数据块
实现

调用内部控制器的 enqueue 方法将数据推入流队列:

this.stream_ctlr.enqueue(data);

必须在调用 start() 后才能使用此方法。


finish()

关闭写入流,表示所有数据已发送完毕。

实现
this.stream_ctlr.close();

通知流结束,触发底层请求完成。


start(controller)

流控制器初始化钩子(由 ReadableStream 调用)。

参数
参数 类型 描述
controller ReadableStreamController 浏览器提供的流控制对象
实现

保存控制器引用以便后续调用:

this.stream_ctlr = controller;

此方法是 ReadableStream 构造时自动调用的标准接口。


函数:bricks.down_streaming

异步生成器函数,用于逐段读取响应流并解码为字符串。

bricks.down_streaming = async function*(response)

参数

参数 类型 描述
response Response 来自 fetch 的响应对象

返回值

  • {AsyncGenerator<string>}:异步生成器,每次 yield 一个字符串片段。

实现逻辑

  1. response 为空,则直接返回。
  2. 获取响应体的读取器:response.body.getReader()
  3. 循环调用 reader.read() 直到流结束(done === true)。
  4. 将每一块 Uint8Array 数据转换为字符串:
    String.fromCharCode(...value.value)
    

    注意:这种方式对非 ASCII 字符(如中文)可能出错,推荐使用 TextDecoder

  5. 输出日志并 yield 结果。

示例用法

for await (const chunk of bricks.down_streaming(resp)) {
  console.log('Received:', chunk);
}

使用示例

上行流发送数据

const uploader = new bricks.UpStreaming({
  url: '/api/stream-upload'
});

// 启动上传
const respPromise = uploader.go();

// 发送若干数据块
uploader.send(new TextEncoder().encode("Hello"));
uploader.send(new TextEncoder().encode("World"));

// 完成上传
uploader.finish();

// 获取响应
const resp = await respPromise;
console.log('Upload complete:', resp.status);

下行流接收数据

const response = await fetch('/api/stream-download');
for await (const textChunk of bricks.down_streaming(response)) {
  console.log('Chunk:', textChunk);
}

注意事项与优化建议

  1. 兼容性警告
    duplex: 'full' 并非所有浏览器都支持,请在使用前检测环境支持情况。

  2. ⚠️ 字符编码问题
    当前行内使用 String.fromCharCode 解码字节数组,不支持 UTF-8 多字节字符
    建议改进为使用 TextDecoder

    const decoder = new TextDecoder('utf-8');
    let result = decoder.decode(value.value);
    
  3. 🔒 错误处理缺失
    当前代码未捕获 fetchreader.read() 中可能出现的异常,建议添加 try-catch

  4. 📦 内存管理
    大量频繁调用 send() 可能导致内存堆积建议结合背压机制backpressure进行流控。


总结

功能 类/函数 用途
流式上传 bricks.UpStreaming 实现双向流上传数据
流式下载解析 bricks.down_streaming 异步解析响应流为字符串

该模块适用于实时音视频通信、大文件分片上传、AI 流式推理等场景,具备良好的扩展潜力。


文档版本v1.0
最后更新2025-04-05