Загрузка из MongDB GridFS перестает работать правильно после определенного количества попыток загрузки - PullRequest
0 голосов
/ 31 октября 2019

Я хочу скачать файл из моей базы данных MongoDB. Я обнаружил, что с использованием корзины GridFS openDownloadStream работает, когда вы передаете его на fs createWriteStream Node, а затем, когда он «заканчивается», вы отправляете эти данные на клиентскую сторону для загрузки с помощью res download. Моя проблема в том, что после нескольких попыток загрузки файлов моя подушка времени ожидания не работает, и клиент не может найти файл вовремя, после чего браузер выдает пустую ошибку ответа. Однако через несколько секунд файл действительно скачивается.

Я интегрирую 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 попыток загрузки. Я в конечном итоге получаю файл, но кажется, что чем больше я загружаю в одном экземпляре сервера, тем больше времени требуется для загрузки -> pipe -> createWriteStream.

РЕДАКТИРОВАТЬ: проблема возникает из-за разрыва связи. Я изменил путь к папке TEMP, но я не хочу хранить эти файлы там навсегда. Я также не хочу отключать их в том же алгоритме, что и их загрузка, так как именно это и вызвало проблему. Любой совет по этому вопросу действительно поможет.

1 Ответ

0 голосов
/ 31 октября 2019

Как указывалось в редактировании, проблема заключалась в вызове unlink практически одновременно с 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)
      }
    })
  }
});
...