Search code examples
node.jsimagemagicknode-asyncnode-request

Resize images right after download in NodeJS, using request and gm modules


I'm trying to resize images right after I've downloaded them using nodejs, request and gm modules but I'm having a hard time understading to pipe stuff properly.

var fs = require('fs');
var path = require('path');
var gm = require('gm').subClass({imageMagick: true});
var request = require('request');
var async = require('async');
var folderImages = './images/';

var q = async.queue(function (task, callback) {

    // Renaming the images
    var thumb350 = task.target.replace('.jpg', '-350.jpg');

    // The target path/images
    var target350 = path.join(folderImages, thumb350);

    // Download the images
    request
        .get(task.PhotoURL)
        .on('response', function(response) {
            console.log(task.PhotoURL + ' : ' + response.statusCode, response.headers['content-type']);
            callback();
        })
        .on('error', function(err) {
            console.log(err);
            callback(err);
        })
        .pipe(fs.createWriteStream(task.target));

    // How can I run this function on files that get downloaded?
    var resizePhotos = gm(task.target)
        .resize('350')
        .write(target350, function (err) {
            if (!err){
                console.log(task.target, ': 350 done');
            }
            else {
                console.log(task.target, ': error');
            }
        });

}, 50);

Solution

  • You can listen the finish event on the writeStream and then put resizing logic in the callback:

    ...
    .pipe(fs.createWriteStream(task.target))
    .on('finish', function(){ 
        //called when writing to disk is complete
        var resizePhotos = gm(task.target)
            .resize('350')
            .write(target350, function (err) {
                if (!err){
                    console.log(task.target, ': 350 done');
                }
                else {
                    console.log(task.target, ': error');
                }
            });
    })