Babr
Babr

Reputation: 2081

How to check whether a directory exists in node.js?

I'd like to save files received from json object in a REST API app and here is the code:

 router.post('/addphoto',  checkAuth, (req, res)=> {
  let filename = Math.floor(Math.random() * 100000);
   let dir = './uploads/' + req.user.id;

//Not sure about this
if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);
}

base64String = req.body.file;
let base64Image = base64String.split(';base64,').pop();
let filePath = dir + "/" + filename

fs.writeFile( filePath, base64Image, {encoding: 'base64'}, function(err) {
console.log('File created');
});
...

It does the job but I've read that existsSync is deprecated, and also I'm not sure if it's a good idea to use sync code inside a router which is async by nature.

So I'm wondering what is the idiomatic way to do so in such circumstances?

Upvotes: 4

Views: 21984

Answers (7)

JRichardsz
JRichardsz

Reputation: 16594

From official docs https://nodejs.org/api/fs.html#fspromisesaccesspath-mode

enter image description here

fs.access will throw an error if file don't exist. So you will not have a boolean to check if file exist or not, like java does from ancient ages. You should use a try/catch:

var isDirExist = false;
try{
    await fs.promises.access("/foo/bar");
    isDirExist = true;
}catch(e){
    isDirExist = false;
}

If this looks problematic, official docs says:

Using fsPromises.access() to check for the accessibility of a file before calling fsPromises.open() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.

Upvotes: 1

Dmitry Vasilev
Dmitry Vasilev

Reputation: 6538

Modern async/await way

const isDirExist = async path => await fs.promises.access(path).then(()=>true).catch(()=>false);

Using


const isDirExist = async path => await fs.promises.access(path).then(()=>true).catch(()=>false);

(async () => {
        
     console.log(await isDirExist('/my/path/'));

})()

Upvotes: 1

aggregate1166877
aggregate1166877

Reputation: 3230

The below code will check if the destination exists. If it doesn't exist, it'll create the destination as a directory. It will also create the parent directories if they don't exist (because of recursive: true). It does not use Sync functions and will not block requests if used in a web server.

const fs = require('fs');

const targetDirectory = 'your/path/here';

fs.mkdir(targetDirectory, { recursive: true }, (error) => {
  if (!error) {
    console.log('Directory successfully created, or it already exists.');
    return;
  }
  switch (error.code) {
    case 'EEXIST':
      // Error:
      // Requested location already exists, but it's not a directory.
      break;
    case 'ENOTDIR':
      // Error:
      // The parent hierarchy contains a file with the same name as the dir
      // you're trying to create.
      break;
    default:
      // Some other error like permission denied.
      console.error(error);
      break;
  }
});

See: mkdir docs.

Upvotes: 0

Mike T
Mike T

Reputation: 614

If you use node-fs-extra you can utilize...

fs.ensureDir(dir[,options][,callback])

Which by definition...

Ensures that the directory exists. If the directory structure does not exist, it is created.

See also fs.ensureDirSync

Upvotes: 0

Quentin
Quentin

Reputation: 944568

I've read that existsSync is deprecated

It isn't. See the manual:

fs.exists() is deprecated, but fs.existsSync() is not. The callback parameter to fs.exists() accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync() does not use a callback.


I'm not sure if it's a good idea to use sync code inside a router which is async by nature.

There's nothing intrinsically wrong about doing something synchronous inside something that is asynchronous — most JS is synchronous — but it does mean that the feature would block the event loop while looking at the file system, and looking at the file system is a relatively time-consuming operation, so it wouldn't be good for performance.

Your code might not need that level of performance, but that's a judgement call we can't make for you.

exists is right next to existsSync in the manual and says:

Deprecated: Use fs.stat() or fs.access() instead.

So pick one of those.

access has an example:

// Check if the file exists in the current directory.
fs.access(file, fs.constants.F_OK, (err) => {
  console.log(`${file} ${err ? 'does not exist' : 'exists'}`);
});

Upvotes: 6

Mohammad Raheem
Mohammad Raheem

Reputation: 1157

You can use access

fs.access(myDir, function(err) {
  if (err && err.code === 'ENOENT') {
    fs.mkdir(myDir); //Create dir in case not found
  }
});

Upvotes: 8

Atishay Jain
Atishay Jain

Reputation: 1445

You can use existsSync as it's not deprecated. it's exists that got deprecated. I've attached a screenshot and link below so you can use it without any problem.

link->

https://nodejs.org/api/fs.html#fs_fs_existssync_path

image->

image

Upvotes: 4

Related Questions