繁体   English   中英

如何在不转换为字符串的情况下将缓冲区直接写入 Node.js 中的 websocket-stream?

[英]How can I write a Buffer directly to websocket-stream in Node.js without converting to string?

这个有点浓。 我正在使用fuse-native package在 Node.js (v14.14.0) 中构建一个基于 web-socket 的 FUSE 文件系统。

为了在客户端和服务器之间传输文件数据,我使用websocket-stream package到 stream 来回传输二进制数据。

这在将文件从服务器传输到客户端时工作正常,但是当尝试将文件从客户端传输到服务器时,我遇到了问题。

fuse-native 通过 Buffer 实例传递文件的二进制段。 我正在尝试将缓冲区写入 websocket-stream stream 并在服务器上接收它,它将被流式传输到一个临时文件。

这是如何发生的。 在客户端,调用以下方法:

write(buffer) {
    console.log('write buffer pre slice', buffer)

    const write_stream = WebSocketStream(`ws://localhost:5746/?socket_uuid=${this.socket_uuid}&node_uuid=${this.node_uuid}&length=${this.length}&position=${this.position}&writing_file=true`, {
        perMessageDeflate: false,
        binary: true,
    })

    console.log(write_stream)
    console.log('writing buffer', buffer.toString(), buffer)

    write_stream.push(buffer)
    write_stream.push(null)
}

根据 Node.js 文档,我应该能够将缓冲区直接传递给 stream。 但是,在服务器上,从未收到任何数据。 以下是服务器接收的方式:

async on_file_write_stream(stream, request) {
    let { socket_uuid, node_uuid, length = 4096, position = 0 } = url.parse(request.url, true).query
    if ( typeof position === 'string' ) position = parseInt(position)
    if ( typeof length === 'string' ) length = parseInt(length)
    const socket = this.sockets.find(x => x.uuid === socket_uuid)

    if ( !socket.session.temp_write_files ) socket.session.temp_write_files = {}

    const placeholder = socket.session.temp_write_files?.[node.uuid] || await tmp.file()
    socket.session.temp_write_files[node.uuid] = placeholder

    console.log('Upload placeholder:', placeholder)
    console.log('write stream', stream)
    console.log('write data', { placeholder, position, length })

    stream.pipe(fs.createWriteStream(placeholder.path, { flags: 'r+', start: position }))
}

一旦客户端代码完成,临时文件仍然是完全空的。 从未写入任何数据。

奇怪的是,当我在将缓冲区写入 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ (在客户端)之前将缓冲区转换为字符串时,一切都按预期工作:

write(buffer) {
    console.log('write buffer pre slice', buffer)

    const write_stream = WebSocketStream(`ws://localhost:5746/?socket_uuid=${this.socket_uuid}&node_uuid=${this.node_uuid}&length=${this.length}&position=${this.position}&writing_file=true`, {
        perMessageDeflate: false,
        binary: true,
    })

    console.log(write_stream)
    console.log('writing buffer', buffer.toString(), buffer)

    write_stream.push(buffer.toString())
    write_stream.push(null)
}

这适用于基于文本的文件,但二进制文件在以这种方式传输时会被破坏。 我怀疑这是因为转移前的字符串。

如何在不先将其转换为字符串的情况下沿 stream 发送缓冲区数据? 我不确定为什么当我直接写入 Buffer 时服务器端 stream 没有接收到数据。

提前致谢。

对于好奇的,这里是完整的服务器端文件客户端文件

有点破解,但我通过 base64 在客户端对缓冲区进行编码并在服务器端对其进行解码来解决这个问题。

感谢用户Bojoer为我指明了组合流库的方向,我曾经使用 pipe 将缓冲区指向 stream:

const combined_stream = CombinedStream.create()
combined_stream.append(buffer.toString('base64'))
combined_stream.pipe(write_stream)

然后,在服务器端对其进行解码:

const encoded_buffer = await this._bufferStream(stream)
const decoded_buffer = new Buffer(encoded_buffer.toString(), 'base64')

console.log({encoded_buffer, decoded_buffer})

const combined_stream = CombinedStream.create()
combined_stream.append(decoded_buffer)
combined_stream.pipe(fs.createWriteStream(placeholder.path, { flags: 'r+', start: position }))

但是,这是次优的,因为从 base64 来回转换需要处理,并且会带来带宽损失。 我仍然很好奇原来的问题为什么我不能将二进制Buffer写入websocket stream。 也许这是图书馆的限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM