Node.js 可写流创建错误文件(更大且不可读)

Posted

技术标签:

【中文标题】Node.js 可写流创建错误文件(更大且不可读)【英文标题】:Node.js Writable Stream creates wrong files (larger and unreadable) 【发布时间】:2016-03-17 02:14:24 【问题描述】:

我正在编写一段代码,通过 Socket.io 将文件从 Angular.js 客户端分块发送到 Node.js 服务器。客户端将文件分块并通过 Socket.io 将它们发送到服务器。

使用javascriptFileReader在客户端读取文件:

var chunkSize = 524288, // 0.5mb
    reader = new FileReader();

reader.onload = function(e) 
    // ok, this one is very simplified so that I don't have to copy
    // all of my code here, but basically I send files with an offset
    // like:
    // file.data.substr(offset, Math.min(chunkSize, file.size - offset));
    // for testing purposes I use a file smaller than 0.5mb, so it
    // gets sent in one chunk
    var chunk = e.target.result.substr(0, chunkSize);   

    // this one is also simplified, I use unique file ids to write to
    // a certain file

    // during testing I use a file of 48014 bytes, if I console.log()
    // it, it says that chunk.length is 48014 bytes
    socket.emit('fileUpload',  chunk: chunk );
;

reader.readAsBinaryString(file);

然后这个事件到达服务器:

// this one is also simplified, in fact I use three events, not one:
// fileUploadStart, fileUpload and fileUploadEnd, but for the sake of
// this question it's irrelevant

socket.on('fileUpload', function(data) 
    var stream = fs.createWriteStream(data.id + '.tmp'));
    stream.on('drain', function() 
        socket.emit('streamDrained',  description: 'Stream drained.', size: stream.bytesWritten );
    );
    stream.write(data.chunk);
);

然后在客户端我收到streamDrained 事件,它告诉我写入了 69127 个字节而不是 48014(这是原始文件的大小)。如果我检查生成的文件,它也是 69127 字节,并且已损坏。原始文件是.pdf,生成的文件可以用PDF阅读器打开,它的页数与原始文件相同,但都是空白的。

另外,如果我console.log()服务器接收到的chunk的长度,也是48014字节长度,但是流写入后,文件竟然是69127字节。

似乎我在FileReaderWritable StreamSocket.io 或它们的任意组合中遗漏了一些东西。非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

这里发生的最有可能是您将二进制数据转换为 UTF-8 字符串,当在二进制数据中发现无效的 UTF-8 字符序列时,这可能会导致额外的字节(无效的替换字符字节) .

要在 socket.io 1.x 中传输二进制数据,您需要确保 chunkBlobArrayBufferFile 实例。那么在节点端,data.chunk 应该是一个包含相同二进制数据的Buffer

一个示例解决方案是使用reader.readAsArrayBuffer() 而不是reader.readAsBinaryString()。还要注意的是reader.readAsBinaryString() is deprecated.

【讨论】:

谢谢,成功了!我使用.readAsArrayBuffer() 并不得不将.subst() 更改为.slice(),除此之外一切正常!

以上是关于Node.js 可写流创建错误文件(更大且不可读)的主要内容,如果未能解决你的问题,请参考以下文章

将数据管道传输到尚未准备好接收数据的可写流

node.js 利用流实现读写同步,边读边写

node.js 核心http模块,起一个服务器,返回一个页面

Node.js——Stream

Node.js学习

如何在具有可写流的循环中按顺序在 Node 中写入流?