Mana Void
Mana Void

Reputation: 387

How to serve a PDF file stored using CollectionFS in Meteor?

I am working on a Meteor application.

Currently, I have a few PDFs on my server. To serve these already existing PDFs directly to the client, I do it this way and it works very well:

Router.route("/file/:fileName", function() {
  var fileName = this.params.fileName;
  // console.log(process.env.PWD);
  var filePath = process.env.PWD + '/' + fileName;
  var fs = Meteor.npmRequire('fs');
  var data = fs.readFileSync(filePath);
  this.response.writeHead(200, {
    "Content-Type": "application/pdf",
    "Content-Length": data.length
  });
  this.response.write(data);
  this.response.end();
}, {
  where: "server"
});

I save these PDFs to Mongo using CollectionFS (Later, I shall generate PDFs and save them. For now, I am just directly saving these already existing PDFs to Mongo as I first want to get the Mongo part to work.).

testCollection = new FS.Collection("testCollection", {
    stores: [new FS.Store.GridFS("testCollection")]
});

testCollection.allow({
    'insert': function () {
        return true;
    }
});

var file = new FS.File(process.env.PWD + '/PDFKitExampleServerSide.pdf');
file.encoding = 'binary';
file.name('myPDF.pdf');
var document = testCollection.insert(file);
console.log(document._id);

My question is, after I save these PDFs to Mongo using CollectionFS (like I do above), how do I retrieve and serve these PDFs?

Router.route("/database/:pdfId", function() {
//need help here
}, { where: "server"});

Upvotes: 0

Views: 681

Answers (2)

Diegaker
Diegaker

Reputation: 21

I know that this question is old, but I found an easier way to store and retrieve PDFs. Apparently if you store your PDFs in the database and they are smaller than 16MB (which is likely in this type of files) the performance is way slower than if you store the files in your server file system.

For doing that, you can use FS.Store.FileSystem instead of FS.Store.GridFS. The following code works for me:

// Client
var pdfStore = new FS.Store.FileSystem("uploadedFiles");
UploadedFiles = new FS.Collection("uploadedFiles", {
  stores: [pdfStore],
  filter: {
    allow: {
      extensions: ['pdf','doc','docx','xls','xlsx','ppt','pptx''jpg','png','jpeg']
    }
  }
});

// Server
var pdfStore = new FS.Store.FileSystem("uploadedFiles", {path: uploadFilesPath});
UploadedFiles = new FS.Collection("uploadedFiles", {
  stores: [pdfStore],
  filter: {
    maxSize: 5242880, // 5MB in bytes
    allow: {
      extensions: ['pdf','doc','docx','xls','xlsx','ppt','pptx''jpg','png','jpeg']
    },
    deny: {
      extensions: ['exe']
    },
    onInvalid: function (message) {
      if (Meteor.isClient) {
        alert(message);
      } else {
        console.log(message);
      }
    }
  }
});

And then just use this little helper to retrieve the url to the file:

  get_uploaded_link: function(id){
    console.log(id);
    var file = UploadedFiles.findOne({_id: id});
    return file.url();}

Upvotes: 0

Mana Void
Mana Void

Reputation: 387

After a lot of searching and trying, I've finally gotten it to work.

Router.route("/database/:pdfId", function() {
    var pdfId = this.params.pdfId;
    var file = testCollection.findOne({_id: pdfId});
    var readable = file.createReadStream("tmp");
    var buffer = new Buffer(0);
    readable.on("data", function(b) {
        buffer = Buffer.concat([buffer, b]);
    });
    var response = this.response;
    readable.on("end", function() {
        response.writeHead(200, {
            "Content-Type": "application/pdf",
            "Content-Length": buffer.length
        });
        response.write(buffer);
        response.end();
    });
}, {
    where: "server"
});

Upvotes: 1

Related Questions