经过一定次数的尝试下载后,从MongDB GridFS下载停止正常工作

问题描述 投票:0回答:1

我想从我的MongoDB数据库下载文件。我发现使用GridFS存储桶的openDownloadStream可以将其通过管道传输到Node的fs createWriteStream,然后在其“完成”时将该数据发送到客户端以使用res下载进行下载。我的问题是几次尝试下载文件后,超时安全缓冲失败,客户端无法及时找到文件,浏览器随后给出了空响应错误。但是,几秒钟后,文件最终会下载。

我正在将mongoDB集成到已经具有下载功能的现有服务器中。以前,文件存储在项目的文件系统中,而现在位于MongoDB中。我已经尝试过运往其他地方,但没有运气。

// Router's Download Logic
router.get("/download", function(req, res) {
  setTimeout(download, 2000);
  function download() {
      var bucket = new mongodb.GridFSBucket(localDatabase())
      bucket.openDownloadStreamByName(file)
        .pipe(fs.createWriteStream(file))
          .on('error', function(error) {
            assert.ifError(error)
          })
          .on('finish', function() {
            console.log(`Downloaded ${file}`)
            res.download(file)
            fs.access(file, function(err) {
              if (err) {
                console.log(err)
              }
              else {
                fs.unlinkSync(file)
              }
            })
          })
  }
});

我希望该文件在2秒的窗口后下载,从而使函数有足够的时间运行。下载大约3次后,我得到的是一个空响应错误。我最终获得了该文件,但似乎我在一台服务器实例中下载的文件越多,下载->管道-> createWriteStream所花费的时间就越长。

编辑:问题来自取消链接。我更改了转到TEMP文件夹的路径,但我不想永远将这些文件存储在其中。我也不想像下载它们一样使用相同的算法取消链接,因为这就是问题所在。关于此的任何建议确实会有所帮助。

node.js mongodb download gridfs
1个回答
0
投票

如编辑中所述,问题实际上是在与res.download同时调用取消链接的情况,这导致了挂断。为了避免这个小窗口,我在删除文件功能中添加了setTimeout。一个可能的错误是当您下载两个文件的速度太快时,为避免这种情况,我发出了警报,让用户知道在等待下载完成之后才尝试再次下载。

router.get("/download", function(req, res) {
  setTimeout(download, 1000);
  function download(callback) {
      var bucket = new mongodb.GridFSBucket(localDatabase())
      bucket.openDownloadStreamByName(file)
        .pipe(fs.createWriteStream('private/TEMP/' + file))
          .on('error', function(error) {
            assert.ifError(err)
          })
          .on('finish', function() {
            res.download('private/TEMP/' + file)
            console.log(`Downloaded ${file}`)
            setTimeout(removeFile, 1200)
          })

  }
  function removeFile() {
    fs.access('private/TEMP/' + file, function(err) {
      if (err) {
        console.log(err)
      }
      else {
        fs.unlinkSync('private/TEMP/' + file)
      }
    })
  }
});
© www.soinside.com 2019 - 2024. All rights reserved.