如何在node.js中检查目录是否存在?

4

我希望在一个REST API应用程序中保存从JSON对象接收到的文件,以下是代码:

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

目前的代码可以完成任务,但是我读到existsSync已经被弃用了,并且我不确定在异步路由器中使用同步代码是否是一个好主意。

因此,我想知道在这种情况下如何做才是最符合惯例的方式?

7个回答

9
您可以使用访问控制。
fs.access(myDir, function(err) {
  if (err && err.code === 'ENOENT') {
    fs.mkdir(myDir); //Create dir in case not found
  }
});

1
这不是正确的解决方案 - 如果myDir 恰好指向一个文件,这将会悄无声息地失败。 - aggregate1166877
我认为这个更好:https://stackoverflow.com/a/32749571/5420070 - undefined

6

我读到了existsSync已经被弃用

这并不是真的。请参见手册:

fs.exists() 已经被弃用,但是 fs.existsSync() 没有被弃用。fs.exists() 的回调参数与其他 Node.js 回调参数不一致。fs.existsSync() 不使用回调。


我不确定在异步路由中使用同步代码是否是一个好主意。
在异步环境中执行同步操作本身并没有什么问题,因为大多数JS都是同步的。但这也意味着该功能将在查看文件系统时阻塞事件循环,而查看文件系统是一个相对耗时的操作,因此对于性能来说并不好。
您的代码可能不需要那么高的性能,但这是我们无法为您做出的判断。
在手册中exists紧挨着existsSync,并表示:
已弃用:请改用fs.stat()或fs.access()。
所以选择其中一个即可。 access有一个示例:
// 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'}`);
});

谢谢你的建议。你能否调整一下 fs.access 的例子以回答我的特定情况? - Babr
1
Access在使用Promises时并不是很好,因为它会依赖于错误来进行合法性检查。 - Eric Burel

4

我明白了。但是在路由器(我想这是异步的)中使用existsSync是个好主意吗? - Babr
没问题,这不需要 Promise 来执行。 - Atishay Jain
为什么需要一个 Promise 来执行?它不需要一个 Promise,因为它是同步的、阻塞式的代码。如果它需要一个 Promise,那么这并不是一个问题,但不使用 Promise 表明它可能存在问题。 - Quentin
@Quentin,这就是我说的。 - Atishay Jain
1
@AtishayJain — 你还是没有理解重点。因为它是同步的,所以它是阻塞的。这就是问题所在。如果它使用了一个 Promise,那是因为它不是同步的,因此不会阻塞。 - Quentin
显示剩余4条评论

1

来自官方文档https://nodejs.org/api/fs.html#fspromisesaccesspath-mode

enter image description here

fs.access会在文件不存在时抛出错误。因此,您将没有一个布尔值来检查文件是否存在,就像Java从古代开始就做的那样。您应该使用try/catch:

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

如果您看到这个提示,官方文档表示:
使用fsPromises.access()在调用fsPromises.open()之前检查文件的可访问性不推荐。这样做会引入竞态条件,因为其他进程可能会在这两个调用之间更改文件的状态。相反,用户代码应该直接打开/读取/写入文件,并处理如果文件不可访问而引发的错误。

1

现代的async/await方式

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

使用


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

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

})()

0

如果你使用 node-fs-extra,你可以利用...

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

根据定义...

确保目录存在。如果目录结构不存在,则创建它。

另请参阅fs.ensureDirSync


0
以下代码将检查目标是否存在。如果不存在,它将创建目标作为目录。如果父目录不存在(因为recursive: true),它还将创建父目录。它不使用同步函数,如果在Web服务器中使用,也不会阻塞请求。
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;
  }
});

请参见:mkdir docs


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接