0

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.

Community
  • 1
  • 1
Kodie Grantham
  • 1,963
  • 2
  • 17
  • 27
  • I don't believe this is possible in the router. The router wants to render an html template. Meteor is going to automatically add the `... ` around the template. – Michel Floyd Jan 16 '17 at 23:20

3 Answers3

1

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!

Kodie Grantham
  • 1,963
  • 2
  • 17
  • 27
0

I thought about this a bit more. You could simply do the following in onAfterAction()

document.type="img";
document.location=url;

However you will lose the router after you do that.

You will still see html in the resulting page because if you open a url to an image in a browser it adds its own html markup around it automatically. To prove this just right-click on an image here and select "open image in new tab"

Michel Floyd
  • 18,793
  • 4
  • 24
  • 39
  • I don't think your answer is going to do what I want it to do still as I have to provide a URL to the file but there isn't one since the file is generated and I want to serve the image buffer in the browser. I'm pretty sure this is possible as people have done the same to serve up file content like this: http://stackoverflow.com/questions/21565991/how-to-serve-a-file-using-iron-router-or-meteor-itself – Kodie Grantham Jan 17 '17 at 15:13
0

You could use Picker for server side routing as it implements Node's ServerResponse module [https://nodejs.org/api/http.html#http_class_http_serverresponse][1] [https://github.com/meteorhacks/picker/][1]

    Picker.route('/i/:cardid/:styleid.png', function(params, req, res, next) {
       var imgContent = Meteor.call('getImage', params.cardid, params.styleid);

  res.writeHead('200', {
    'Content-Type': 'image/png',
    'Content-Length': imgContent.length
  });

 res.end(imgContent);
    });
Yack
  • 51
  • 5
  • I feel like this is possible in Iron Router I'm just doing something wrong as people have done the same to serve up file content like this: http://stackoverflow.com/questions/21565991/how-to-serve-a-file-using-iron-router-or-meteor-itself – Kodie Grantham Jan 17 '17 at 15:14
  • So you want to expose a `data:` link then? That's doable. – Michel Floyd Jan 17 '17 at 19:34
  • I'm not entirely sure but that sounds right. I basically would like to generate and serve up the image when the user visits the URL. So if I were to do something like `[img src="http://mywebsite.com/i/323/1.png"]`. The image would be generated based on the path. – Kodie Grantham Jan 17 '17 at 20:28
  • Michel Floyd, can you give me more info on exposing the `data:` link? I have updated my original post a little. – Kodie Grantham Jan 18 '17 at 17:30