admin管理员组

文章数量:1333400

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

本文标签: javascriptHow to write multiple files using Nodejs createReadStream and createWriteStreamStack Overflow