【问题标题】:File Upload in NodeJs with express-fileupload not working properly使用 express-fileupload 在 NodeJs 中上传文件无法正常工作
【发布时间】:2019-06-19 08:39:59
【问题描述】:

我已经在 NodeJs 中创建了一个用于文件上传的 REST API 工作正常,但是有一个问题,如果我上传超过 2 个图像,则只有 2 个,3 个被上传,有时 1 个被损坏。我认为我的循环运行得太快了。 打击是我的代码:

app.post('/img-upload', function(req, res) {
  if (!req.files)
    return res.status(400).send({"status":"false", "data":"Image Not Found"});

  // Use the mv() method to place the file somewhere on your server
    for(var key in req.files) {

        thisFile = req.files[key];
        let name = +new Date();
        thisFile.mv('./images/' + name++ +'.png', function(err) {
            if (err) {
                res.send(err);
            }   

        });

    }
        res.json({"status":"File uploaded!"});
});

使用的模块:express-fileupload

【问题讨论】:

  • res.json() 可能会导致请求在文件上传完成之前关闭。您必须等到每个回调完成。
  • 你能解释更多吗!
  • 两个文件可能被移动到同一个目标路径。就像你说的,循环飞得很快。对new Date() 的调用很可能会在两次迭代中返回相同的值。一种解决方案是将计数器变量 name 移到循环体之外。

标签: javascript node.js rest express for-loop


【解决方案1】:

发布一个可能不是答案的答案,以解释@PatrickRoberts 的评论似乎有道理。

thisFile.mv 显然是异步工作的,这意味着 function(err){...} 可能会在 res.json(...) 和以下隐式 return 之后运行。

虽然 Node 不应该终止剩余的异步进程,但无论如何你告诉用户文件已成功上传还为时过早。 (您可以发送该成功,然后您的一个回调会抛出一个错误......但为时已晚,您无法将该错误发送给客户端。)

有两个选项可以解决这个问题。

不错的选择

等待所有回调完成以发送成功结果。大概是这样的:

let uploads = [];
for (let k in req.files) {
  req.files[k].mv('/my/path/to.png', function(err) {
    let promise = new Promise(function(resolve, reject) {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
    uploads.push(promise);

  })
} // end for loop
Promise.all(uploads).then(function() {
  res.json({"status":"File uploaded!"});
}).catch(function(err) {
  res.send(err);
});

一个让我感到羞耻的缓慢选择

如果这不能解决问题,并且假设@PatrickRoberts 发现了正确的问题,您可以尝试按顺序进行上传,例如:

function processFile() {
  let file = req.files.shift()
  if (!file) return; // stop sequence condition
  file.mv('/my/path/to.png', function(err) {
    if (err) {
      res.send(err);
    } else {
      processFile();
    }
  })
}
processFile(); // start the recursive and sequential "loop"

如果这些都不起作用(第二个不好的选择很慢,但可以清楚地证明是否涉及res.json/res.send),那么您的问题出在其他地方。在这种情况下,请提供有关“有时已损坏”的更多信息:文件是否不完整?是服务器显示错误吗?客户端收到错误?在后一种情况下,会出现什么错误?

【讨论】:

  • 我已经尝试了一切......正如你所说,在所有文件之前停止发送响应。我和我的 PHP 朋友讨论过,他说你的循环运行速度太快,无法处理更多文件,他们使用sleep() 来减慢循环速度。 “有时一个已损坏”:这意味着如果我发送 5 个文件 2 个正常上传,第 3 个已上传但未打开,则表示文件已损坏,其余 2 个已丢失....
  • 您是否尝试过实施我提出的第二种故障安全方法?此外,这可能与网络问题有关:尝试仅上传轻量级的 1kB 文件?
  • 我试过你的方法,但没有成功。单个文件上传正常。 2 个或更多文件导致问题...
  • 你用什么来实现req.files属性和file.mv方法?
  • express-fileupload
【解决方案2】:

这对我有用

 let media = req.files; 

 for (let pos in media) {
   media[pos].mv(`./media/${renameFile}`, (err) => {
        if (err) {
            return res.status(500).json({
                ok: false,
                err
            });
        }
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 2013-11-16
    • 2023-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多