错误 运行 Node.js' fs.rename() 在循环内
Error running Node.js' fs.rename() inside of a loop
我正在开发一个应用程序,它必须组织一些上传的文件,我用他们请求的 ID 将它们放在文件夹中(我正在使用 express-request-id 来获取这个 ID)。
问题是,每当我有多个文件时,"moving" 进程就会失败,我似乎无法修复它。
let request_folder = path.resolve(tmp_folder + "/" + req.id);
/* Checking if the folder exists */
fs.access(request_folder, fs.constants.F_OK, function(error) {
if(error) { // it doesn't
/* Trying to create it */
fs.mkdir(request_folder, function(error) {
if(error) {
console.log("Error: Couldn't create the directory.");
console.log(error);
}
});
}
});
/* Moving uploaded files to their respective request folder */
req.files.forEach(function(file) {
let new_file_path = path.resolve(request_folder + "/" + file.filename);
fs.rename(file.path, new_file_path, function(error) {
if(error) {
console.log("Error: Couldn't move " + file.filename + ".");
console.log(error);
}
});
});
我百分百确定文件夹和文件都存在,但是我在尝试一次移动两个文件时得到:
Error: Couldn't move Desert.jpg.
{ Error: ENOENT: no such file or directory, rename 'C:\Users\telmo.silva\csc-links\public\tmp\Desert.jpg' -> 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73
\Desert.jpg'
errno: -4058,
code: 'ENOENT',
syscall: 'rename',
path: 'C:\Users\telmo.silva\csc-links\public\tmp\Desert.jpg',
dest: 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73\Desert.jpg' }
Error: Couldn't move Chrysanthemum.jpg.
{ Error: ENOENT: no such file or directory, rename 'C:\Users\telmo.silva\csc-links\public\tmp\Chrysanthemum.jpg' -> 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f
5725a73\Chrysanthemum.jpg'
errno: -4058,
code: 'ENOENT',
syscall: 'rename',
path: 'C:\Users\telmo.silva\csc-links\public\tmp\Chrysanthemum.jpg',
dest: 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73\Chrysanthemum.jpg' }
有谁知道我做错了什么?谢谢!
您使用的 fs
操作是异步的,这意味着它们可以按任何顺序发生。
你的循环将要求节点创建一个文件夹并基本上同时移动文件。换句话说,它将 运行 一个同步循环,将同时调度所有 fs
操作。这意味着您无法保证实际上 运行 首先是什么。
尝试在移动所有文件之前创建文件夹:
fs.access(request_folder, fs.constants.F_OK, function(error) {
if(error) {
return fs.mkdir(request_folder, function(error) {
if(error) {
return;
}
moveFiles();
});
}
moveFiles();
});
function moveFiles() {
req.files.forEach(function(file) {
// ...
});
}
使用 promises 可能会使它更简洁:
const access = util.promisify(fs.access);
const mkdir = util.promisify(fs.mkdir);
const rename = util.promisify(fs.rename);
access(request_folder, fs.constants.F_OK)
.then(moveFiles, makeDirAndMoveFiles)
.catch(console.error);
function moveFiles() {
return Promise.all(
req.files.map(file => {
const new_file_path = path.resolve(request_folder + "/" + file.filename);
return rename(file.path, new_file_path);
})
)
}
function makeDirAndMoveFiles() {
return mkdir(request_folder).then(moveFiles);
}
您可能在目标文件夹存在之前就尝试移动文件。
尝试使用新的 await 关键字来构建代码。
const {promisify} = require('util');
const fs = require('fs');
const accessFileAsync = promisify(fs.access);
const mkdirFileAsync = promisify(fs.mkdir);
const renameFileAsync = promisify(fs.rename);
try{
await accessFileAsync(request_folder, fs.constants.F_OK);
}
catch(ex)
{
await mkdirFileAsync(request_folder);
}
req.files.forEach(function(file) {
let new_file_path = path.resolve(request_folder + "/" + file.filename);
try{
await renameFileAsync(file.path, new_file_path);
}
catch(ex)
{
console.log(ex);
}
});
我正在开发一个应用程序,它必须组织一些上传的文件,我用他们请求的 ID 将它们放在文件夹中(我正在使用 express-request-id 来获取这个 ID)。
问题是,每当我有多个文件时,"moving" 进程就会失败,我似乎无法修复它。
let request_folder = path.resolve(tmp_folder + "/" + req.id);
/* Checking if the folder exists */
fs.access(request_folder, fs.constants.F_OK, function(error) {
if(error) { // it doesn't
/* Trying to create it */
fs.mkdir(request_folder, function(error) {
if(error) {
console.log("Error: Couldn't create the directory.");
console.log(error);
}
});
}
});
/* Moving uploaded files to their respective request folder */
req.files.forEach(function(file) {
let new_file_path = path.resolve(request_folder + "/" + file.filename);
fs.rename(file.path, new_file_path, function(error) {
if(error) {
console.log("Error: Couldn't move " + file.filename + ".");
console.log(error);
}
});
});
我百分百确定文件夹和文件都存在,但是我在尝试一次移动两个文件时得到:
Error: Couldn't move Desert.jpg.
{ Error: ENOENT: no such file or directory, rename 'C:\Users\telmo.silva\csc-links\public\tmp\Desert.jpg' -> 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73
\Desert.jpg'
errno: -4058,
code: 'ENOENT',
syscall: 'rename',
path: 'C:\Users\telmo.silva\csc-links\public\tmp\Desert.jpg',
dest: 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73\Desert.jpg' }
Error: Couldn't move Chrysanthemum.jpg.
{ Error: ENOENT: no such file or directory, rename 'C:\Users\telmo.silva\csc-links\public\tmp\Chrysanthemum.jpg' -> 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f
5725a73\Chrysanthemum.jpg'
errno: -4058,
code: 'ENOENT',
syscall: 'rename',
path: 'C:\Users\telmo.silva\csc-links\public\tmp\Chrysanthemum.jpg',
dest: 'C:\Users\telmo.silva\csc-links\public\tmp\d2abf375-d09f-440c-a5ba-adf4f5725a73\Chrysanthemum.jpg' }
有谁知道我做错了什么?谢谢!
您使用的 fs
操作是异步的,这意味着它们可以按任何顺序发生。
你的循环将要求节点创建一个文件夹并基本上同时移动文件。换句话说,它将 运行 一个同步循环,将同时调度所有 fs
操作。这意味着您无法保证实际上 运行 首先是什么。
尝试在移动所有文件之前创建文件夹:
fs.access(request_folder, fs.constants.F_OK, function(error) {
if(error) {
return fs.mkdir(request_folder, function(error) {
if(error) {
return;
}
moveFiles();
});
}
moveFiles();
});
function moveFiles() {
req.files.forEach(function(file) {
// ...
});
}
使用 promises 可能会使它更简洁:
const access = util.promisify(fs.access);
const mkdir = util.promisify(fs.mkdir);
const rename = util.promisify(fs.rename);
access(request_folder, fs.constants.F_OK)
.then(moveFiles, makeDirAndMoveFiles)
.catch(console.error);
function moveFiles() {
return Promise.all(
req.files.map(file => {
const new_file_path = path.resolve(request_folder + "/" + file.filename);
return rename(file.path, new_file_path);
})
)
}
function makeDirAndMoveFiles() {
return mkdir(request_folder).then(moveFiles);
}
您可能在目标文件夹存在之前就尝试移动文件。
尝试使用新的 await 关键字来构建代码。
const {promisify} = require('util');
const fs = require('fs');
const accessFileAsync = promisify(fs.access);
const mkdirFileAsync = promisify(fs.mkdir);
const renameFileAsync = promisify(fs.rename);
try{
await accessFileAsync(request_folder, fs.constants.F_OK);
}
catch(ex)
{
await mkdirFileAsync(request_folder);
}
req.files.forEach(function(file) {
let new_file_path = path.resolve(request_folder + "/" + file.filename);
try{
await renameFileAsync(file.path, new_file_path);
}
catch(ex)
{
console.log(ex);
}
});