簡體   English   中英

在循環內運行Node.js的fs.rename()時出錯

[英]Error running Node.js' fs.rename() inside of a loop

我正在開發一個必須整理一些上傳文件的應用程序,將它們與請求ID分離在文件夾中(我正在使用express-request-id來獲取此ID)。

問題是,每當我有多個文件時,“移動”過程都會失敗,並且我似乎無法修復它。

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

使用諾言可能會使它更簡潔:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM