Search code examples
javascriptnode.jspdfmeteoriron-router

Rendering a PDF using Meteor and Iron Router


I have a pdf file located here:

/server/.files/users/test.pdf

When I display a link on a page, I'd like for the user to be able to click the link, and for the pdf to be rendered on the screen.

I've read through this SO post in particular, and others, but cannot seem to get things to work: SO Link

I tried using an IR route server side, but every time I try even something simple I get the following error:

Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions. at Object.Meteor.userId

(packages/accounts-base/accounts_server.js:19:1) at Object.Meteor.user (packages/accounts-base/accounts_server.js:24:1) at [object Object].Router.onBeforeAction.except (app/both/3-router/routes.js:10:15) at packages/iron:router/lib/router.js:277:1 at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1) at [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1) at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1) at packages/meteor/dynamics_nodejs.js:121:1 at [object Object].dispatch (packages/iron:middleware-stack/lib/middleware_stack.js:275:1)

Line: #10 in my router.js file is the first if statement here:

Router.onBeforeAction(function () {   
   if (!Meteor.user() || Meteor.loggingIn()) {
    this.redirect('welcome.view');   }   else {
    Meteor.call("userFileDirectory", function (error, result) {
      if (error)
        throw error;
      else
        console.log(result);
    });
    this.next();   
 } }, {   except: ['welcome.view'] });

I tried this:

Router.map(function() {
    this.route('serverFile', {
        where: 'server',
        path: /^\/uploads_url_prefix\/(.*)$/,
        action: function() {
           var filePath = process.env.PWD + '/.files/users/' + this.params[1];
           var data = fs.readFileSync(filePath);
           this.response.writeHead(200, {
                'Content-Type': 'image'
           });
           this.response.write(data);
           this.response.end();
        }
    }); });

But I'm not sure what to put in the path.


Solution

  • With process.env.PWD you are in the directory of your meteor project. so you should be able to access your file like this:

    var file = process.env.PWD + "/server/.files/users/test.pdf"
    

    To use the fs package of node you also need to include it and you need to be on the server:

    Router.route('/pdf', function() {
        var filePath = process.env.PWD + "/server/.files/users/test.pdf";
        var fs = Meteor.npmRequire('fs');
        var data = fs.readFileSync(filePath);
        this.response.write(data);
        this.response.end();
    }, {
        where: 'server'
    });
    

    Make sure to this package to your project (https://atmospherejs.com/meteorhacks/npm)

    meteor add meteorhacks:npm
    

    I tested it and it is working like a charm!