为二进制块创建元数据以通过 WebRTC 数据通道发送
Creating meta-data for binary chunks for sending via WebRTC datachannel
我在两个浏览器之间建立了数据通道连接,我想将文件分成多个块并将它们发送给 to/from 客户端。
我可以读取文件并将其分解成块。但是我需要一种方法让接收客户端知道
数据块与哪个文件相关(唯一标识符)。
重建时chunk应用于哪个地方(索引号)
在浏览器中传输二进制数据时,似乎整个负载必须是二进制的。所以我不能,例如,创建一个具有上述属性的 JSON 对象,并有一个 data
属性 与实际的二进制块。
我想我需要将文件块包装到包含标识符和索引的辅助二进制 blob 中。然后,接收客户端将解码第一个包装器块以检查元数据,然后根据该信息处理实际文件块。
如何在浏览器中执行此操作?我进行了大量 google 搜索,但似乎找不到任何相关信息,所以想知道我是否忽略了一些有助于简化此过程的内容?
您必须创建自己的文件传输协议。
- 我假设您有一个
File
/Blob
对象。您可能还使用 split()
方法来获取块。
您可以简单地使用Uint8Array传输数据。
创建满足您需求的协议,例如:
- 1 字节:包类型(255 种可能的包类型)
- 2 字节:数据长度(每个块 2^16 字节 ~ 64KB 数据)
- n 字节:<数据>
发送初始包(例如键入 0x01)
- 数据包含一些信息(全部或部分):
- 总长度blob/file
- 文件类型
- 块大小
- 块数
- 文件名
- ...
发送数据块(例如类型 0x02)
- 序列号至少应使用两个字节
- 之后是数据(不需要长度,因为你知道总长度)
注意:如果传输多个文件,你应该添加一个id或其他东西。
在接收方,您可以等待初始包并创建一个新的 Uint8Array
,其长度为整个文件的长度。之后您可以使用 set()
将接收到的数据添加到块位置(偏移量 = 0-based-chunk-number
*chunk-size
)。收到所有块后,您可以创建 Blob
.
除了@Robert 的非常好的答案之外,您还可以使用 channel.send(blob)(至少在 Firefox<->Firefox 中)。最终这也应该适用于 Chrome。
如果是多个文件的简单问题,您可以为每个新文件创建一个新的数据通道。
每个通道都会处理它自己的缓冲、序列等。
类似于:
chan = peerCon.createDataChannel("/somedir/somefile", props);
然后将您的文件分成 <64k 块并按顺序 chan.send()
它们。
接收方可以获取标签并使用它来适当地保存文件
peerCon.ondatachannel = function(channel) {
console.log("New file " + channel.label);
channel.onmessage = function(
等等
P.S。
如果你真的必须在单个通道上使用文件系统协议(比如因为你想要随机访问行为)不要发明一个新的,使用一个已经存在并经过测试的协议 - 我喜欢来自 [=27= 的 9p ]
我在两个浏览器之间建立了数据通道连接,我想将文件分成多个块并将它们发送给 to/from 客户端。
我可以读取文件并将其分解成块。但是我需要一种方法让接收客户端知道
数据块与哪个文件相关(唯一标识符)。
重建时chunk应用于哪个地方(索引号)
在浏览器中传输二进制数据时,似乎整个负载必须是二进制的。所以我不能,例如,创建一个具有上述属性的 JSON 对象,并有一个 data
属性 与实际的二进制块。
我想我需要将文件块包装到包含标识符和索引的辅助二进制 blob 中。然后,接收客户端将解码第一个包装器块以检查元数据,然后根据该信息处理实际文件块。
如何在浏览器中执行此操作?我进行了大量 google 搜索,但似乎找不到任何相关信息,所以想知道我是否忽略了一些有助于简化此过程的内容?
您必须创建自己的文件传输协议。
- 我假设您有一个
File
/Blob
对象。您可能还使用split()
方法来获取块。 您可以简单地使用Uint8Array传输数据。
创建满足您需求的协议,例如:
- 1 字节:包类型(255 种可能的包类型)
- 2 字节:数据长度(每个块 2^16 字节 ~ 64KB 数据)
- n 字节:<数据>
发送初始包(例如键入 0x01)
- 数据包含一些信息(全部或部分):
- 总长度blob/file
- 文件类型
- 块大小
- 块数
- 文件名
- ...
- 数据包含一些信息(全部或部分):
发送数据块(例如类型 0x02)
- 序列号至少应使用两个字节
- 之后是数据(不需要长度,因为你知道总长度)
注意:如果传输多个文件,你应该添加一个id或其他东西。
在接收方,您可以等待初始包并创建一个新的 Uint8Array
,其长度为整个文件的长度。之后您可以使用 set()
将接收到的数据添加到块位置(偏移量 = 0-based-chunk-number
*chunk-size
)。收到所有块后,您可以创建 Blob
.
除了@Robert 的非常好的答案之外,您还可以使用 channel.send(blob)(至少在 Firefox<->Firefox 中)。最终这也应该适用于 Chrome。
如果是多个文件的简单问题,您可以为每个新文件创建一个新的数据通道。
每个通道都会处理它自己的缓冲、序列等。
类似于:
chan = peerCon.createDataChannel("/somedir/somefile", props);
然后将您的文件分成 <64k 块并按顺序 chan.send()
它们。
接收方可以获取标签并使用它来适当地保存文件
peerCon.ondatachannel = function(channel) {
console.log("New file " + channel.label);
channel.onmessage = function(
等等
P.S。 如果你真的必须在单个通道上使用文件系统协议(比如因为你想要随机访问行为)不要发明一个新的,使用一个已经存在并经过测试的协议 - 我喜欢来自 [=27= 的 9p ]