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
1 Answer
Reset to default 5You 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);
}