【问题标题】:Cancel File Upload: Multer, MongoDB在 MEAN 堆栈应用程序中取消文件上传
【发布时间】:2021-02-25 16:58:05
【问题描述】:

我似乎找不到任何关于如何使用 Mongo、NodeJS 和 Angular 取消文件上传的最新答案。我只遇到过一些关于如何删除文件的教程,但这不是我正在寻找的。我希望能够通过单击前端的按钮来取消文件上传过程。

我使用 Mongoose、Multer 和 GridFSBucket 包将我的文件直接存储到 MongoDB 中。我知道我可以通过取消订阅前端负责上传的订阅者来停止前端的文件上传过程,但是当我上传时,上传过程会继续在后端进行取消订阅**(是的,我已经检查了两次和三次。在文件完全上传之前,所有块都会不断上传。)

这是我的 Angular 代码

  ngOnInit(): void {
    // Upload the file.
    this.sub = this.mediaService.addFile(this.formData).subscribe((event: HttpEvent<any>) => {
      console.log(event);
      switch (event.type) {
        case HttpEventType.Sent:
          console.log('Request has been made!');
          break;
        case HttpEventType.ResponseHeader:
          console.log('Response header has been received!');
          break;
        case HttpEventType.UploadProgress:
          // Update the upload progress!
          this.progress = Math.round(event.loaded / event.total * 100);
          console.log(`Uploading! ${this.progress}%`);
          break;
        case HttpEventType.Response:
          console.log('File successfully uploaded!', event.body);
          this.body = 'File successfully uploaded!';
      }
    },
    err => {
      this.progress = 0;
      this.body = 'Could not upload the file!';
    });
  }


  **CANCEL THE UPLOAD**
  cancel() {
    // Unsubscribe from the upload method.
    this.sub.unsubscribe();
  }

这是我的 NodeJS (Express) 代码

...

// Configure a strategy for uploading files.
const multerUpload = multer({ 
    // Set the storage strategy.
    storage: storage,
    // Set the size limits for uploading a file to 120MB.
    limits: 1024 * 1024 * 120,
    // Set the file filter.
    fileFilter: fileFilter
}); 

// Add new media to the database.
router.post('/add', [multerUpload.single('file')], async (req, res)=>{
    return res.status(200).send();
});

什么是取消上传而不在数据库中留下任何块的正确方法?

【问题讨论】:

    标签: node.js angular file-upload multer multer-gridfs-storage


    【解决方案1】:

    尝试使用try catch方式。

    有两种方法可以做到。

    1. 通过调用将当前上传的文件作为参数的 api,然后在后端执行删除和清除服务器上存在的块的步骤

    2. 通过处理异常。
      通过发送文件大小作为验证,如果后端 api 已接收到完全与其大小相同的文件,则将保留该文件,或者如果接收到的文件的大小较小,这是由于取消上传 bin 而导致的,则执行清除您只需获取文件的 id 和 mongoose db 并清除它的步骤。

    【讨论】:

    • 我无法删除尚未完全上传的文件,因为 MongoDB 将媒体文件数据分成 2 个集合:media.chunks 和 media.files。为了删除存储在 media.chunks 集合中的文件块,您需要存储在 media.files 集合中的文件元数据。如果文件尚未完全上传,则元数据不会出现在 media.files 集合中。有没有办法在上传时检查文件是否已完全上传?或者如果没有达到预期的文件大小,有什么方法可以抛出异常?
    【解决方案2】:

    所以我这两天一直在努力解决这个问题,我相信我找到了一个令人满意的解决方案:

    首先,为了取消文件上传并删除任何已经上传到MongoDB的chunk,你需要在你的multer配置中调整fileFilter这样一种检测请求是否已中止以及上传流是否已结束的方法。然后通过使用 fileFilter 的回调抛出错误来拒绝上传:

    // Adjust what files can be stored.
    const fileFilter = function(req, file, callback){
        console.log('The file being filtered', file)
    
        req.on('aborted', () => {
            file.stream.on('end', () => {
                console.log('Cancel the upload')
                callback(new Error('Cancel.'), false);
            });
            file.stream.emit('end');
        })
    }
    

    注意:取消文件上传时,您必须等待更改显示在您的数据库中。在从数据库中删除取消的文件之前,必须首先上传已经发送到数据库的块。这可能需要一段时间,具体取决于您的网速和取消上传之前发送的字节数。

    最后,您可能想在后端设置一个路由来从文件中删除尚未完全上传到数据库的所有块(由于一些错误这可能是在上传过程中发生的)。为此,您需要从 .chunks 集合 (by following the method specified on this link) 中获取所有文件 ID,并将其块已部分上传到数据库的文件的 ID 与文件的 ID 分开已完全上传。然后,您需要在这些 ID 上调用 GridFSBucket 的 delete() 方法,以消除冗余块。此步骤纯粹是可选的,并且出于数据库维护的原因。

    【讨论】:

      猜你喜欢
      • 2017-09-20
      • 1970-01-01
      • 2019-11-24
      • 2017-08-07
      • 2019-07-29
      • 1970-01-01
      • 2017-03-09
      • 2020-01-19
      • 1970-01-01
      相关资源
      最近更新 更多