首页 > 解决方案 > 在 Nestjs 中使用 multipart/form-data

问题描述

我需要将 pdf 文件上传到第三方 API 来完成我们使用控制器的操作,然后将其缓冲区发送到 multipart/form-data 中的端点,但它不起作用。我究竟做错了什么??

我的控制器定义为

    @Post('/upload')
    @UseInterceptors(FileInterceptor('file'))
    async uploadDocument(@UploadedFile() file: Express.Multer.File){
        await this.httpRequestService.uploadDocument(file)
        return [
            Translation.translate('Create_Success_Message', {
                Entity: 'File'
            }),
            {
                file
            }
        ]
    }

此控制器调用一个名为的服务uploadDocument,如下所示:

async uploadDocument(file){
        try{
        const formData = new FormData()
        formData.append('file', file)
        const response = await this.httpService.post(`urlWhereItHits`,
        formData, 
        {   
            headers:{ 
                "X-AppSecretToken":"appsecrettoken",
                "X-AgreementGrantToken":"agreementgranttoken",
                'Content-Type' : 'multipart/form-data'
            },
            
        }).toPromise();
        }
        catch(error){
            console.log(error)
        }
}

现在我不明白这里发生了什么错误。我收到错误消息
TypeError: source.on is not a function at Function.DelayedStream.create (C:\Users\Tushar\Squire-backend\node_modules\delayed-stream\lib\delayed_stream.js:33:10)

标签: nestjs

解决方案


我有一个类似的任务,接收一个 .csv 文件并将其发送到另一台服务器。

控制器:

    @UseInterceptors(FileInterceptor('file'))
    @Post('upload')
    async uploadFile(@UploadedFile() file: Express.Multer.File) {
      
      await this.myService.uploadFile(file);
      return {
        message: 'File uploaded successfully.',
      };
    }

服务:

    import * as FormData from 'form-data';
    import { Readable } from 'stream';
    
    async uploadFile(file: Express.Multer.File) {
    const form = new FormData();

    form.append('files', Readable.from(file.buffer), {
      filename: file.originalname,
    });

    try {
      const result = await lastValueFrom(
        this.httpService.post('The URL of your third-party service', form, {
          headers: {
            ...form.getHeaders(),
          },
        }),
      );

      if (result.status === 200) return;
    } catch {
      
      throw new InternalServerErrorException(
        'Error while uploading the .csv file.',
      );
    }
    }

这里有一些解释:

  • Formdata它需要从中导入。
  • .append()需要一个 fieldName 和一个可读的 Stream。
  • 您可以使用内存中文件的缓冲区(不建议用于大文件)并使用它来创建可读流。
  • 此外,您需要手动添加文件名,因为Formdata仅当文件保存在磁盘上时才能识别文件名。(在我们的例子中,它作为缓冲区在内存上)。
  • 您可以通过不同的方式创建流,示例不是强制性的。
  • .getHeaders()将生成默认标题'Content-Type': 'multipart/form-data',也会生成文件的边界,如下所示
      {
        'content-type': 'multipart/form-data; boundary=--------------------------286308325485491440714225'
      }

推荐阅读