Question

I've written a simple image manipulation service that uses node gm on an image from an http response stream. If I use nodejs' default transfer-encoding: chunked, things work just fine. But, as soon as I try and add the content-length implementation, nodejs hangs the response or I get content-length mismatch errors.

Here's the gist of the code in question (variables have been omitted due to example):

    var image = gm(response);
    // gm getter used to get origin properties of image
    image.identify({bufferStream: true}, function(error, value){
      this.setFormat(imageFormat)
        .compress(compression)
        .resize(width,height);

      // instead of default transfer-encoding: chunked, calculate content-length
      this.toBuffer(function(err, buffer){
        console.log(buffer.length);
        res.setHeader('Content-Length', buffer.length);
        gm(buffer).stream(function (stError, stdout, stderr){
          stdout.pipe(res);
        });
      });
    });

This will spit out the desired image and a content length that looks right, but the browser will hang suggesting that there's a bit of a mismatch or something else wrong. I'm using node gm 1.9.0.

I've seen similar posts on nodejs gm content-length implementation, but I haven't seen anyone post this exact problem yet.

Thanks in advance.

Was it helpful?

Solution

I ended up changing my approach. Instead of using this.toBuffer(), I save the new file to disk using this.write(fileName, callback), then read it with fs.createReadStream(fileName) and piping it to the response. Something like:

var filePath = './output/' + req.param('id') +'.' + imageFormat;
this.write(filePath, function (writeErr) {
  var stat = fs.statSync(filePath);                         
  res.writeHead(200, {
    'Content-Type': 'image/' + imageFormat,
    'Content-Length': stat.size
  });

  var readStream = fs.createReadStream(filePath);
  readStream.pipe(res);

  // async delete the file from filesystem
  ...
});

You end up getting all of the headers you need including your new content-length to return to the client.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top