Node.js Writable Stream创建错误的文件(更大且不可读)

时间:2015-12-11 08:17:40

标签: angularjs node.js sockets socket.io

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

使用javascript的FileReader

在客户端上读取文件
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()服务器收到的块的长度,它的长度也是48014字节,但在写入流后,文件结果为69127字节。

似乎我在FileReaderWritable StreamSocket.io或{{1}}或其任何组合的概念中都缺少某些内容。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

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

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

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