首页 > 解决方案 > 在 node.js 中保存文件时,如果文件名已经存在,则增加文件名?

问题描述

有没有一种简单的方法可以让 node.js 在保存文件时增加文件的文件名(即附加一个数字,这样它就不会覆盖以前的文件)?

以下是我的尝试:

// can i make this a one-liner?:)
async function incrementIfExists(dirPath, fileName, data, increment=1) {
    const fs = require('fs'),
        path = require('path'),
        errorFunc = (err) => console.error(err);
        
    // Get the last file saved with same fileName (i.e., the one that has the greatest increment number), if there is one   
    let lastFile = await fs.promises.readdir(dirPath) 
        .then(files => {
            let result = '';
            
            for (const name of files) {
                if (!name.startsWith(fileName)) continue;
                if ((name.length < result.length) || (name.length === result.length && name < result)) continue;
                result = name;
            }
            
            return result;
        })
        
        .catch(errorFunc);
        
    if (lastFile) {
        const lastIncrementNr = Number(lastFile.slice((fileName + '_').length));
        if (increment <= lastIncrementNr) increment = lastIncrementNr + 1;
    }
    
    fileName = path.join(dirPath, fileName);
    
    while (true) {
        let breakLoop = await fs.promises.writeFile(lastFile ? fileName + '_' + increment : fileName, data, {encoding: 'utf8', flag: 'wx'})
            
            .then(fd => true)
            
            .catch(err => {
                if (err.code === 'EEXIST') {console.log(err);
                    return false;
                }
                throw err;
            });
        
        if (breakLoop) break;
        increment++;
    }
}

incrementIfExists('.', fileName, data);

相关:
如何在 node.js 中不覆盖文件
仅在 Node.js 中不存在文件时才创建文件

标签: node.jssave

解决方案


我使用类似于在磁盘上上传图像文件的版本。我决定使用“EEXIST”错误来增加数字,而不是显式地迭代目录中的文件。

const writeFile = async(filename, data, increment = 0) => {
  const name = `${path.basename(filename, path.extname(filename))}${increment || ""}${path.extname(filename)}`
  return await fs.writeFile(name, data, { encoding: 'utf8', flag: 'wx' }).catch(async ex => {
    if (ex.code === "EEXIST") return await writeFile(filename, data, increment += 1)
    throw ex
  }) || name
}
const unversionedFile = await writeFile("./file.txt", "hello world")
const version1File = await writeFile("./file.txt", "hello world")
const version2File = await writeFile("./file.txt", "hello world")


推荐阅读