Reputation: 4402
I would like to give you a background first.
I have an array of image parameters just like below:
"imageParameters": [
{
"imageparam1": "param1",
"imageparam2": "param2",
"imageparam3": "param3"
},
{
"imageparam1": "param1",
"imageparam2": "param2",
"imageparam3": "param3"
}
]
I loop through this to generate unique urls per image. Then trigger the downloadImageAndSave function each time url is generated.
imageParameters.forEach(function (image) {
var imageUrL = baseURL + "¶m1=" + image.imageparam1 + "¶m2=" + image.imageparam2 + "¶m3=" + image.imageparam3 ;
var imageparam1 = image.imageparam1;
downloadImageAndSave(imageUrL, imageparam1);
});
function downloadImageAndSave(imageUrL, imageparam1) {
console.log("Download function is triggered")
var fs = require('fs'),
request = require('request');
request
.get(imageUrL)
.on('error', function(err) {
// handle error
})
.pipe(fs.createWriteStream('./imagesLocation/' + imageparam1 + '.jpeg'));
myfunctionTobeTRiggeredAfterImagesDownloadedAndSaved();
}
How do I know all of these images are downloaded and saved so that I can trigger my function?
The problem I am having is to use the callback. I am not how I can get callback once all of the images are downloaded and saved.
Any help would be much appreciated. Thank you.
UPDATED
Below is the workflow I am trying to achieve. I get an input from the user via express API like this.
app.get('/getStudyID', function(req, res) {
var id = req.query['getStudyID'];
//pass this to a variable to be used by various functions.
downloadImagesToNodeServer(id);
zipImageFiles();
returnTheZipFileBackToUser(id);
}
Then return the zipped file which contains the images back to the user.
function returnTheZipFileToUser(id) {
var path = require('path');
var mime = require('mime');
var file = __dirname + '/public/imagelocation/' + id + '.zip';
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
}
The returnTheZipFileToUser is called too early before the images are downloaded and zipped. Therefore I get the image.zip file not found problem as it is triggered way too early before the zipImageFiles() and downloadImagesToNodeServer.
I found a hacky way to implement the setTimeout to wait for the downloads to finish then trigger the returnTheZipFileToUser(id). But this is not a real solution as the timing is different depending on the size of the images and the zip file. So I need a surefire way that the images are downloaded completely and zipped file is ready before the returnTheZipFileToUser is called.
Upvotes: 1
Views: 448
Reputation: 3651
If you return the stream from downloadImageAndSave
, you could then use something like stream-concat to concat all of the streams into a single stream that you could listen for the finish event:
function downloadImages(imageParameters, cb) {
var streams = imageParameters.map(function (image) {
var imageUrL = baseURL + "¶m1=" + image.imageparam1 + "¶m2=" + image.imageparam2 + "¶m3=" + image.imageparam3 ;
var imageparam1 = image.imageparam1;
return downloadImageAndSave(imageUrL, imageparam1);
});
var combinedStream = new StreamConcat(streams);
combinedStream.on('error', function(error) {
cb(error);
});
combinedStream.on('finish', function() {
cb();
});
}
function downloadImageAndSave(imageUrL, imageparam1) {
console.log("Download function is triggered")
var fs = require('fs'),
request = require('request');
return request
.get(imageUrL)
.on('error', function(err) {
// handle error
})
.pipe(fs.createWriteStream('./imagesLocation/' + imageparam1 + '.jpeg'));
}
Upvotes: 2