Search code examples
javascriptnode.jsmeteorcanvasiron-router

How to generate images server-side in Meteor and serve them via Iron Router?


Like the title says, I just want to generate an image on the server and then serve it up in the browser via Iron Router.

Here's what I have so far:

server/methods.js:

Meteor.methods({
  getImage(cardId, styleId) {
    var canvas = new Canvas(500, 200);
    var ctx = canvas.getContext('2d');

    ctx.font = '26px "Comic Sans"';
    ctx.fillText('Hello World', 50, 80);

    var buffer = canvas.toBuffer();
    buffer = canvas.toDataURL();

    return buffer;
  }
});

routes/routes.js:

Router.route('/i/:cardid/:styleid.png', function() {
  var imgContent = Meteor.call('getImage', this.params.cardid, this.params.styleid);
  //imgContent = `<html><body><img src="${imgContent}"></body></html>`;

  this.response.writeHeader('200', {
    'Content-Type': 'image/png',
    'Content-Length': imgContent.length
  });

  this.response.write(imgContent);

  this.response.end();
}, {where: 'server'});

If I uncomment the line in routes.js and comment out the image/png header, I can get the image to display inside of an HTML image tag, however this isn't want I want as I just want to serve up the actual image, no HTML.

Any help would be greatly appreciated. Thanks!

EDIT I've also tried returning this:

var buffer = canvas.toBuffer();
//buffer = canvas.toDataURL();

buffer = new Buffer(buffer, 'binary').toString('base64');

With no success.

File contents without image/png header

File contents with image/png header

EDIT 2 Basically I'm trying to do this: NodeJS: serve png generated by node-canvas but with just Meteor, Canvas, and Iron Router.


Solution

  • I was able to get it working by doing the following:

    server/methods.js:

    Meteor.methods({
      getImage(cardId, styleId) {
        var canvas = new Canvas(500, 200);
        var ctx = canvas.getContext('2d');
    
        ctx.font = '26px "Comic Sans"';
        ctx.fillText('Hello World', 50, 80);
    
        return canvas.toBuffer();
      }
    });
    

    routes/routes.js

    Router.route('/i/:cardid/:styleid.png', function() {
      var imgContent = Meteor.call('getImage', this.params.cardid, this.params.styleid);
      imgContent = new Buffer(imgContent, 'binary');
    
      this.response.writeHeader('200', {
        'Content-Type': 'image/png',
        'Content-Length': imgContent.length
      });
    
      this.response.write(imgContent);
    
      this.response.end();
    }, {where: 'server'});
    

    Basically just needed to output the right kind of data!