最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to write multiple files using Node.js createReadStream and createWriteStream - Stack Overflow

programmeradmin1浏览0评论

Okay here is the general goal of this code. I am using TinyPNG's API to condense a folder of png files. I have an input folder with a number of files named filename.png. This code reads the directory of file names into an array files, then creates read and write streams for those files to be sent to the API, processed, and then returned so it can be written to a file in the output folder. I know the code works for one file, but any more than that throws an exception of write after end because the pipe is automatically closed after the first one. I have tried setting up the input and output as arrays and that just throws another exception.

Any hints on how to set up multiple read and write streams would be awesome and very useful to everyone :).

Current code:

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("");
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);
      }

});

Here is the fixed file for others to use thanks to the answer provided by @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("");
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");
        }
    });
} 

Okay here is the general goal of this code. I am using TinyPNG's API to condense a folder of png files. I have an input folder with a number of files named filename.png. This code reads the directory of file names into an array files, then creates read and write streams for those files to be sent to the API, processed, and then returned so it can be written to a file in the output folder. I know the code works for one file, but any more than that throws an exception of write after end because the pipe is automatically closed after the first one. I have tried setting up the input and output as arrays and that just throws another exception.

Any hints on how to set up multiple read and write streams would be awesome and very useful to everyone :).

Current code:

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./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);
      }

});

Here is the fixed file for others to use thanks to the answer provided by @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./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");
        }
    });
} 
Share Improve this question edited Oct 7, 2017 at 4:12 Styx 10.1k8 gold badges48 silver badges56 bronze badges asked Dec 20, 2013 at 18:57 thebaron24thebaron24 3151 gold badge3 silver badges8 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

You are repeatedly reassigning the output variable in your loop, while the request callback is trying to refer to it. You can capture each value in a closure to get around this.

...

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);
 }
发布评论

评论列表(0)

  1. 暂无评论