如何使用Node.js的createReadStream和createWriteStream写入多个文件

3

好的,这段代码的总体目标是使用TinyPNG的API来压缩一个文件夹中的png文件。我有一个带有许多名为filename.png的文件的输入文件夹。该代码将文件名目录读入数组files中,然后创建读取和写入流以便将它们发送到API进行处理,再将其返回以便写入输出文件夹中的文件中。我知道该代码适用于一个文件,但是对于多个文件,在第一个文件之后会抛出“ write after end”的异常,因为管道在第一个文件之后会自动关闭。我已经尝试将输入和输出设置为数组,但只会引发另一个异常。

如何设置多个读和写流的任何提示都将非常棒且对所有人非常有用:)。

当前代码:

var fs = require('fs');
var inputFolder = "input/";
var outputFolder = "output/";
var https = require("https");

var key = "GETYOUROWNFREEONEFROMTINYPNG.ORG";

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

var options = require("url").parse("https://api.tinypng.com/shrink");
options.auth = "api:" + key;
options.method = "POST";

console.log("Reading files...");

fs.readdir("./input", function (err, files) {

  if (err) throw err;

  console.log(files.length + " files read...");

  var input;
  var output;
  var request;

      for(var i = 0; i < files.length; i++)
      {
        input = fs.createReadStream(inputFolder + files[i]);
        output = fs.createWriteStream(outputFolder + files[i]);

          request = new https.request(options, function(response) {
            if (response.statusCode === 201) {
              /* Compression was successful, retrieve output from Location header. */
              https.get(response.headers.location, function(response) {
                response.pipe(output);
              });
            } else {
              /* Something went wrong! You can parse the JSON body for details. */
              console.log("Compression failed");
            }
          });

          input.pipe(request);
      }

});

感谢@Wyatt提供的答案,这里是修复后的文件,供其他人使用:

var fs = require('fs');
var inputFolder = "input/";
var outputFolder = "output/";
var https = require("https");

var key = "WotZ46HnxPl_HwpT3uZjtY_0f8fMEiSR";

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

var options = require("url").parse("https://api.tinypng.com/shrink");
options.auth = "api:" + key;
options.method = "POST";

console.log("Reading files...");

fs.readdir("./input", function (err, files) {

  if (err) throw err;

  console.log(files.length + " files read...");

  var input, request;

  for(var i = 0; i < files.length; i++){
    input = fs.createReadStream(inputFolder + files[i]);
    request = closureRequest(fs.createWriteStream(outputFolder + files[i]));
    input.pipe(request);
  }

});


function closureRequest(output){
    return new https.request(options, function(response) {
        if (response.statusCode === 201) {
          /* Compression was successful, retrieve output from Location header. */
          https.get(response.headers.location, function(response) {
            response.pipe(output);
          });
        } else {
          /* Something went wrong! You can parse the JSON body for details. */
          console.log("Compression failed");
        }
    });
} 
1个回答

5

在你的循环中,你不断地重新分配输出变量,而请求回调正在尝试引用它。你可以通过闭包捕获每个值来解决这个问题。

...

function closureRequest(output){
    return new https.request(options, function(response) {
        if (response.statusCode === 201) {
          /* Compression was successful, retrieve output from Location header. */
          https.get(response.headers.location, function(response) {
            response.pipe(output);
          });
        } else {
          /* Something went wrong! You can parse the JSON body for details. */
          console.log("Compression failed");
        }
    });
}

var input
  , request
  ;

for(var i = 0; i < files.length; i++){
    input = fs.createReadStream(inputFolder + files[i]);
    request = closureRequest(fs.createWriteStream(outputFolder + files[i]));
    input.pipe(request);
 }

1
以惊人的速度提供了出色的答案。可能因为你回答得太快了,有一个错别字 - 在for循环中,这一行:request = closureRequest(fs.createWriteStream(outputFolder + files[i]); 应该是 request = closureRequest(fs.createWriteStream(outputFolder + files[i])); 你漏掉了一个括号来关闭closureRequest。感谢你的回答。 - thebaron24

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接