NodeJs:二进制fs.createReadStream流式传输为UTF-8

时间:2015-11-28 20:36:28

标签: node.js utf-8 stream

我的任务是读取NodeJ中的jpeg文件并将其作为http响应发送以回答服务器请求。似乎是微不足道的。但是,我的第一个解决方案失败浏览器确实收到了一些二进制文件,比原始文件大30%。

我的代码是(简化; res是SeverResponse类型):

...
var fs = require('fs');
var stream = fs.createReadStream(pathToJPEG, {encoding: 'binary'});
res.setHeader('Content-Type', "image/jpeg");
stream.pipe(res);
...

事实证明,到达浏览器的是源数据的UTF-8编码版本。我也能够将响应对象排除在罪魁祸首之外。当我给它一个替代流(来自缓冲区,而不是文件)时,它运行得很好。

原来解决我的问题的方法是删除选项{encoding:' binary'}。我的浏览器收到了正确的图片:

...
var fs = require('fs');
var stream = fs.createReadStream(pathToJPEG);
res.setHeader('Content-Type', "image/jpeg");
stream.pipe(res);
...

我的问题是:为什么?

看起来很直观,第一个非工作版本应该是正确的版本,因为它明确声明了如何读取文件。

2 个答案:

答案 0 :(得分:3)

这是因为binary编码实际上不是binarycreateReadStream使用Buffer接受的相同encoding个参数。来自Node Buffer Docs

  

'binary' - 一种将缓冲区编码为单字节(即latin-1)编码字符串的方法。不支持字符串'latin-1'。而只是简单地传递'二进制'来使用'latin-1'编码。

只需将编码设置为null即可获取原始流或缓冲区,或者根本不像第二个示例中那样指定任何内容。

答案 1 :(得分:0)

Ixe是正确的,将编码更改为null可行,但仅在升级到较新的node / express程序包之后。这是我的代码,可以正确上传tar文件:

    fs.exists(filePath, function(exists){
    if (exists) {
        var stat = fs.statSync(filePath);
        console.log('sending file, size %d', stat.size);

        res.writeHead(200, {
            "Content-Type": "application/x-tar",
            "Content-Disposition": "attachment; filename=" + filePath,
            "Content-Length": stat.size,
            "Content-Transfer-Encoding": "binary"
        });
        fs.createReadStream(filePath, { encoding: null }).pipe(res);    //must set encoding to null, as binary is not treated correctly

    } else {
        console.log('file not exist.');
        res.writeHead(400, {"Content-Type": "text/plain"});
        res.end("ERROR File does not exist");
    }
});