当前位置: 首页 > 面试题库 >

Node.js:如何将流读入缓冲区?

邢炯
2023-03-14
问题内容

我写了一个非常简单的函数,可以从给定的URL下载图像,调整图像大小并上传到S3(使用’gm’和’knox’),我不知道我是否在正确地将流读取到缓冲区中。(一切正常,但这是正确的方法吗?)

另外,我想了解一些有关事件循环的知识,如何知道该函数的一次调用不会泄漏任何内容,也不会将’buf’变量更改为另一个已经运行的调用(否则这种情况是不可能的,因为回调是匿名的功能?)

var http = require('http');
var https = require('https');
var s3 = require('./s3');
var gm = require('gm');

module.exports.processImageUrl = function(imageUrl, filename, callback) {
var client = http;
if (imageUrl.substr(0, 5) == 'https') { client = https; }

client.get(imageUrl, function(res) {
    if (res.statusCode != 200) {
        return callback(new Error('HTTP Response code ' + res.statusCode));
    }

    gm(res)
        .geometry(1024, 768, '>')
        .stream('jpg', function(err, stdout, stderr) {
            if (!err) {
                var buf = new Buffer(0);
                stdout.on('data', function(d) {
                    buf = Buffer.concat([buf, d]);
                });

                stdout.on('end', function() {
                    var headers = {
                        'Content-Length': buf.length
                        , 'Content-Type': 'Image/jpeg'
                        , 'x-amz-acl': 'public-read'
                    };

                    s3.putBuffer(buf, '/img/d/' + filename + '.jpg', headers, function(err, res) {
                        if(err) {
                            return callback(err);
                        } else {
                            return callback(null, res.client._httpMessage.url);
                        }
                    });
                });
            } else {
                callback(err);
            }
        });
    }).on('error', function(err) {
        callback(err);
    });
};

问题答案:

总的来说,我看不到任何会破坏您代码的东西。

两个建议:

合并Buffer对象的方式不是最佳选择,因为它必须在每个“数据”事件上复制所有预先存在的数据。最好将大块放在一个数组中,然后将concat它们全部放在最后。

var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
  var buf = Buffer.concat(bufs);
}

为了提高性能,我将调查您使用的S3库是否支持流。理想情况下,您根本不需要创建一个大缓冲区,只需将stdout流直接传递到S3库即可。

至于问题的第二部分,那是不可能的。调用函数时,将为其分配自己的私有上下文,并且只能从该函数内定义的其他项访问该函数内定义的所有内容。

更新资料

将文件转储到文件系统可能会减少每个请求的内存使用量,但是文件IO可能非常慢,因此可能不值得。我想说,除非可以对此功能进行概要分析和压力测试,否则不要进行过多优化。如果垃圾收集器正在执行其工作,则可能是过度优化了。

综上所述,总有更好的方法,所以不要使用文件。由于所需的只是长度,因此您可以计算该长度而无需将所有缓冲区附加在一起,因此根本就不需要分配新的Buffer。

var pause_stream = require('pause-stream');

// Your other code.

var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
  var contentLength = bufs.reduce(function(sum, buf){
    return sum + buf.length;
  }, 0);

  // Create a stream that will emit your chunks when resumed.
  var stream = pause_stream();
  stream.pause();
  while (bufs.length) stream.write(bufs.shift());
  stream.end();

  var headers = {
      'Content-Length': contentLength,
      // ...
  };

  s3.putStream(stream, ....);


 类似资料:
  • 问题内容: 在使用stream2接口之后,如何将node.js缓冲区转换为Readable流? 问题答案: 使用流化器,您可以使用新的流API将字符串和缓冲区转换为可读流。

  • 我如何能转换一个node.js缓冲区到一个可读流以下使用Streum2接口? 我已经找到了这个答案和streambuffers模块,但是这个模块基于stream1接口。

  • 问题内容: 我有一个Java程序,它将一些文本输出到控制台。它使用,和其他一些方法来执行此操作。 在程序的最后,我想读取控制台中的所有文本并将其复制到String缓冲区中。我该如何用Java做到这一点?我需要阅读和独立。 问题答案: 好的,这是一个有趣的问题。似乎不是一种同时解决所有方法的优雅方法。(不幸的是没有。) 我确实写了一个丑陋的基于反射的解决方法(我想不要在生产代码中使用它:) …可以像

  • JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。 但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。 在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二

  • 问题内容: 我正在入侵用于捕获SMTP电子邮件并处理邮件数据的Node程序。该库将邮件数据作为流提供,但我不知道如何将其转换为字符串。 我目前正在使用将其写入stdout ,但是正如我所说,我需要将流数据替换为字符串,一旦流结束,就可以使用它。 如何将所有数据从Node.js流收集到字符串中? 问题答案: 关键是使用Readable Stream 的和事件。听这些事件: 收到事件后,将新的数据块添

  • 问题内容: 问:我怎样才能从读到的一切入的方式是不是一个手工制作的循环用我自己的字节的缓冲区? 问题答案: 编写一个方法来执行此操作,然后从需要该功能的任何地方调用它。番石榴已经在中提供了代码。我敢肯定,几乎所有其他具有“通用” IO功能的库也都有它,但是Guava是我第一个“入门”库。它震撼了:)