Node.js 可写流创建了错误的文件(更大且不可读)
Node.js Writable Stream creates wrong files (larger and unreadable)
我正在编写一段代码,通过 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打开-reader,它与原始文件的页数相同,但都是空白。
另外,如果我console.log()
服务器接收到的chunk的长度也是48014字节,但是写完流后,文件变成了69127字节。
似乎我在 FileReader
或 Writable Stream
或 Socket.io
或它们的任何组合的概念中遗漏了一些东西。非常感谢任何帮助。
这里发生的很可能是您将二进制数据转换为 UTF-8 字符串,当在二进制数据。
要在 socket.io 1.x 中传输二进制数据,您需要确保 chunk
是 Blob
、ArrayBuffer
或 File
实例。那么在节点端,data.chunk
应该是一个包含相同二进制数据的Buffer
。
一个示例解决方案是使用 reader.readAsArrayBuffer()
instead of reader.readAsBinaryString()
. It should also be noted that reader.readAsBinaryString()
is deprecated.
我正在编写一段代码,通过 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打开-reader,它与原始文件的页数相同,但都是空白。
另外,如果我console.log()
服务器接收到的chunk的长度也是48014字节,但是写完流后,文件变成了69127字节。
似乎我在 FileReader
或 Writable Stream
或 Socket.io
或它们的任何组合的概念中遗漏了一些东西。非常感谢任何帮助。
这里发生的很可能是您将二进制数据转换为 UTF-8 字符串,当在二进制数据。
要在 socket.io 1.x 中传输二进制数据,您需要确保 chunk
是 Blob
、ArrayBuffer
或 File
实例。那么在节点端,data.chunk
应该是一个包含相同二进制数据的Buffer
。
一个示例解决方案是使用 reader.readAsArrayBuffer()
instead of reader.readAsBinaryString()
. It should also be noted that reader.readAsBinaryString()
is deprecated.