NestJS FilesInterceptor 不解析来自 Axios 请求的文件

问题描述

我有一个使用 FilesInterceptor 处理多部分/表单数据上传的控制器。

  @Post('/upload/:serial')
  @UseInterceptors(FilesInterceptor('files[]'))
  uploadLogFiles(
    @UploadedFiles() files: UploadLog[],@Param('serial') serial: number,@Req() request: Request
  ): LogUploadResponse {
    const upLoadedfiles = this.logPersistenceService.persistFiles(
      files,serial
    );
    return { files: upLoadedfiles };
  }
}

当我通过 Postman 创建的请求提交文件时,文件被成功解析出请求。

但是,当我尝试使用基于 Axios 的 HttpServiceForm-Data 库通过 nest 创建请求时,我无法从请求中获取文件

const formData = new FormData();
formData .append('files[]','a,b,c',fileName);

this.httpService
      .post<LogUploadResponse>(
        `${this.restUrl}/api/logging/upload/${serial}`,formData,{
          headers: formData.getHeaders()
        }
      )

我已验证控制器正在接收请求,但 files 为空。我已经通过管道将 formData 传输到 WriteStream,内容看起来不错,边界也与标题中的内容相匹配。

----------------------------347967411467094575699495
Content-disposition: form-data; name="files[]"; filename="a.log"
Content-Type: text/plain

a,c
----------------------------347967411467094575699495--
REQUEST Headers { accept: 'application/json,text/plain,*/*','content-type':
   'multipart/form-data; boundary=--------------------------347967411467094575699495',referer: 'http://localhost/','user-agent':
   'Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML,like Gecko) jsdom/15.2.1','accept-language': 'en',origin: 'http://localhost',host: 'localhost:8081','accept-encoding': 'gzip,deflate','content-length': '17',connection: 'keep-alive' }

更新 如果我直接使用 node http 模块而不是 nestJS/Axios,我可以让它工作

作品

    const form = new FormData();

    for (const file of Object.keys(files)) {
      form.append('files[]',files[file],file);
    }
    return new Promise<LogUploadResponse>((resolve,reject) => {
      const req = request(
        {
          method: 'POST',hostname: 'localhost',port: 8081,path: `/api/logging/upload/${serial}`,headers: form.getHeaders()
        },res => {
          res.on('error',r => {
            reject(r.message);
          });
          res.on('data',r => {
            console.log('**r',r.toString());
            resolve(r.toString());
          });
        }
      );
    form.pipe(req);

不起作用

    const form = new FormData();

    for (const file of Object.keys(files)) {
      form.append('files[]',file);
    }
    const req = this.httpService.request<LogUploadResponse>({
      baseURL: 'http://localhost:8081',url: `/api/logging/upload/${serial}`,method: 'POST',data: form,headers: form.getHeaders()
    });

    return req
      .pipe(
        tap(resp => console.log('status',resp.status)),map(resp => resp.data),catchError(_err => of({ files: [] }))
      )
      .toPromise();

我查看了 GitHub 中 http.js 的 Axios 源代码,看起来它正在对流数据进行管道处理,但我没有深入挖掘。

解决方法

始终无法使 Axios 版本正常工作,只是在我的应用程序中为此特定请求实现了节点 http 版本。