Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render Image Stored in Mongo (GridFS) with Node + Jade + Express

I have a small .png file stored in Mongo using GridFS. I would like to display the image in my web browser using Node + Express + Jade. I can retrieve the image fine e.g.:

FileRepository.prototype.getFile = function(callback,id) {
this.gs = new GridStore(this.db,id, 'r');
this.gs.open(callback);
};

but I don't know how to render it using the Jade View Engine. There doesn't seem to be any information in the documentation.

Can anyone point me in the right direction?

Thanks!

like image 358
Click Ahead Avatar asked Mar 23 '12 18:03

Click Ahead


People also ask

How to use GridFS with MongoDB?

When you want to keep your files and metadata automatically synced and deployed across a number of systems and facilities, you can use GridFS. When using geographically distributed replica sets, MongoDB can distribute files and their metadata automatically to a number of mongod instances and facilities. Since, GridFS stores files in chunks.

How to upload images to MongoDB using Node JS?

Run the command: node src/server.js Open your browser with url http://localhost:8080/, add some images like this: Click on Submit button. If these images are uploaded and stored in MongoDB successfully, you can see:

What is the best way to store an image in MongoDB?

If you need to store the actual file on MongoDB, then GridFS is the way to go (as suggested by @Sudhesh_Gnanasekaran ). However there is an alternative – store a url to an image in your document.

How to connect to MongoDB using Multer-GridFS-storage?

url: must be a standard MongoDB connection string pointing to the MongoDB database. multer-gridfs-storage module will create a mongodb connection for you automatically. options: customizes how to establish the connection, specified in the MongoClient.connect documentation. file: this is the function to control the file storage in the database.


2 Answers

I figured this out (thanks Timothy!). The problem was my understanding of all these technologies and how they fit together. For anyone else who's interested in displaying images from MongoDB GridFS using Node, Express and Jade ...

My Document in MongoDB has a reference to the Image stored in GridFS which is an ObjectId stored as a string. e.g. MyEntity {ImageId:'4f6d39ab519b481eb4a5cf52'} <-- NB: String representation of ObjectId. The reason I stored it as a string was because storing the ObjectId was giving me a pain in the Routing as it was rendering as binary and I couldn't figure out how to fix this. (Maybe someone can help here?). Anyway, the solution I have is below:

FileRepository - Retrieve the image from GridFS, I pass in a String Id, which I then convert to a BSON ObjectId (you can also get the file by file name):

FileRepository.prototype.getFile = function(callback,id) {
   var gs = new GridStore(this.db,new ObjectID(id), 'r');
   gs.open(function(err,gs){
      gs.read(callback);
   });
 };

Jade Template - Render the HTML Markup:

img(src='/data/#{myentity.ImageId}')

App.JS file - Routing (using Express) I setup the '/data/:imgtag' route for dynamic images:

app.get('/data/:imgtag', function(req, res) {
  fileRepository.getFile( function(error,data) {
     res.writeHead('200', {'Content-Type': 'image/png'});
     res.end(data,'binary');
  }, req.params.imgtag );
});

And that did the job. Any questions let me know :)

like image 119
Click Ahead Avatar answered Oct 22 '22 16:10

Click Ahead


I'm a little confused about what you're trying to do here, as Jade is a condesed markup language for text output (such as HTML), not binary content.

Since you're using Jade you probably have something like this:

app.get/'images/:imgtag', function(req, res) {
    res.render('image', {imgtag: req.params.imgtag);
});

So try this:

app.get/'images/:imgtag', function(req, res) {
    filerep.getFile( function(imgdata) {
        res.header({'Content_type': 'image/jpeg'})
        res.end(imgdata);
    }, req.params.imgtag );
});

That will send the raw file as a response to the HTTP request with the correct mime type. If you want to use Jade to deliver a template (such as an image popup) you could use a different route for the popup or even use a data: uri and encode the image data in the page.

like image 25
Timothy Meade Avatar answered Oct 22 '22 17:10

Timothy Meade