Lite Byte
Lite Byte

Reputation: 689

Fastest way to check for existence of a file in NodeJs

I'm building a super simple server in node and in my onRequest listener I'm trying to determine if I should serve a static file (off the disk) or some json (probably pulled from mongo) based on the path in request.url.

Currently I'm trying to stat the file first (because I use mtime elsewhere) and if that doesn't fail then I read the contents from disk. Something like this:

fs.stat(request.url.pathname, function(err, stat) {
    if (!err) {
        fs.readFile(request.url.pathname, function( err, contents) {
            //serve file
        });
    }else {
        //either pull data from mongo or serve 404 error
    }
});

Other than cacheing the result of fs.stat for the request.url.pathname, is there something that could speed this check up? For example, would it be just as fast to see if fs.readFile errors out instead of the stat? Or using fs.createReadStream instead of fs.readFile? Or could I potentially check for the file using something in child_process.spawn? Basically I just want to make sure I'm not spending any extra time messing w/ fileio when the request should be sent to mongo for data...

Thanks!

Upvotes: 34

Views: 32840

Answers (4)

julianalimin
julianalimin

Reputation: 188

In case you want to serve a file using express, I would recommend to just use the sendFile error Handler of express

const app = require("express")();

const options = {};
options.root = process.cwd();

var sendFiles = function(res, files) {
  res.sendFile(files.shift(), options, function(err) {
    if (err) {
      console.log(err);
      console.log(files);
      if(files.length === 0) {
        res.status(err.status).end();
      } else {
        sendFiles(res, files)
      }
    } else {
      console.log("Image Sent");
    }
  });
};

app.get("/getPictures", function(req, res, next) {
  const files = [
    "file-does-not-exist.jpg",
    "file-does-not-exist-also.jpg",
    "file-exists.jpg",
    "file-does-not-exist.jpg"
  ];

  sendFiles(res, files);

});

app.listen(8080);

If the file is not existent then it will go to the error that sends it self. I made a github repo here https://github.com/dmastag/ex_fs/blob/master/index.js

Upvotes: 0

Salar
Salar

Reputation: 5509

this snippet can help you

fs = require('fs') ;
var path = 'sth' ;
fs.stat(path, function(err, stat) {
    if (err) {
        if ('ENOENT' == err.code) {
            //file did'nt exist so for example send 404 to client
        } else {
            //it is a server error so for example send 500 to client
        }
    } else {
        //every thing was ok so for example you can read it and send it to client
    }
} );

Upvotes: 2

fent
fent

Reputation: 18205

var fs = require('fs');

fs.exists(file, function(exists) {
  if (exists) {
    // serve file
  } else {
    // mongodb
  }
});

Upvotes: 58

alessioalex
alessioalex

Reputation: 63663

I don't think you should be worrying about that, but rather how can you improve the caching mechanism. fs.stat is really ok for file checking, doing that in another child process would probably slow you down rather then help you here.

Connect implemented the staticCache() middleware a few months ago, as described in this blog post: http://tjholowaychuk.com/post/9682643240/connect-1-7-0-fast-static-file-memory-cache-and-more

A Least-Recently-Used (LRU) cache algo is implemented through the Cache object, simply rotating cache objects as they are hit. This means that increasingly popular objects maintain their positions while others get shoved out of the stack and garbage collected.

Other resources:
http://senchalabs.github.com/connect/middleware-staticCache.html
The source code for staticCache

Upvotes: 2

Related Questions