5

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?

7 Answers 7

9

You can use access

fs.access(myDir, function(err) {
  if (err && err.code === 'ENOENT') {
    fs.mkdir(myDir); //Create dir in case not found
  }
});
Sign up to request clarification or add additional context in comments.

2 Comments

This is not the right solution - if myDir just so happens to point to a file, this will silently fail.
I think this is better: stackoverflow.com/a/32749571/5420070
7

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'}`);
});

2 Comments

Thanks for the tips. Can you please adjust the fs.access example to answer my particular case?
Access does not sound very good with promises as it would rely on errors for a legitimate check
4

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

9 Comments

I see. But is it a good idea to use existsSync inside the router (which I suppose is async) ?
Yes that's not a problem at all as it doesn't require promise to execute.
Why would it need a promise to execute? It doesn't need a promise because it is synchronous, blocking code. If it needed a promise then it wouldn't be a problem, but not using one indicates that it could be.
@AtishayJain — Still the opposite of what I said, which is that as it does not require a promise it could be a problem.
@AtishayJain — You continue to miss the point. Because it is synchronous it is blocking. That is the problem. If it used a promise it would be because it wasn't synchronous and thus not blocking.
|
1

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/'));

})()

Comments

1

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.

Comments

0

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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.