NestJS:使用 StreamableFile 从缓冲区返回 PDF 文件

Age*_*ic_ 7 node.js typescript nestjs

我正在使用 NestJS 8.0.2,并且尝试使用新的StreamableFile类从 API 端点返回 PDF,正如文档所述:

StreamableFile 是一个保存要返回的流的类。要创建新的 StreamableFile,您可以将 Buffer 或 Stream 传递给 StreamableFile 构造函数。

我正在使用一个名为 pdfMake 的 PDF 打印库,它提供了一个选项,可以将 PDF 作为Buffer对象从内存返回。如果可能的话,我试图避免将生成的 PDF 保存到文件系统,而是直接返回它。

所以我尝试通过执行以下操作将两者结合起来:

pdf-service.ts

async generatePDF(inputs: PDFInputsDTO) {
  try {
    const definition = this.generateDocDefinition(inputs);
    const document = pdfMake.createPdf(definition);
    const promise = new Promise((resolve, reject) => {
      try {
        document.getBuffer((result) => {
          resolve(result); // result is of type Buffer
      } catch (e) {
        reject(e);
      }
    });

    return promise as Promise<Buffer>;
  } catch (e) {
    throw new InternalServiceException('PDF generation error');
  }
}
Run Code Online (Sandbox Code Playgroud)

pdf-controller.ts

@Post('pdf')
@HttpCode(200)
@UseFilters(ValidationExceptionFilter)
@UsePipes(new ValidationPipe(PdfController.pipeOptions))
@Header('Content-Type', 'application/pdf')
@Header('Content-Disposition', 'inline; filename=file.pdf')
async generatePDFFile(@Body() inputs: PDFInputsDTO) {
  try {
    const pdfFile = await this.pdfService.generatePDF(inputs);

    console.log(`PDF is: ${pdfFile}`); // prints "PDF is: <Buffer 25 50 44 46 2d 31 2e 33 0a 25 ff ff ff ff 0a 39 20 30 20 6f 62 6a 0a 3c 3c 0a 2f 54 79 70 65 20 2f 45 78 74 47 53 74 61 74 65 0a 2f 63 61 20 31 0a 2f ... >"

    return new StreamableFile(pdfFile);
  } catch(e) {
    throw(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

这会导致异常:

[Nest] 26539  - 07/24/2021, 4:14:33 PM   ERROR [ExceptionsHandler] Cannot read property 'pipe' of undefined
TypeError: Cannot read property 'pipe' of undefined
    at ExpressAdapter.reply (/Users/agentlogic/Work/Web/Backend/pdf-generator/node_modules/@nestjs/platform-express/adapters/express-adapter.js:27:36)
    at RouterResponseController.apply (/Users/agentlogic/Work/Web/Backend/pdf-generator/node_modules/@nestjs/core/router/router-response-controller.js:14:36)
    at /Users/agentlogic/Work/Web/Backend/pdf-generator/node_modules/@nestjs/core/router/router-execution-context.js:175:48
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at /Users/agentlogic/Work/Web/Backend/pdf-generator/node_modules/@nestjs/core/router/router-execution-context.js:47:13
    at /Users/agentlogic/Work/Web/Backend/pdf-generator/node_modules/@nestjs/core/router/router-proxy.js:9:17
Run Code Online (Sandbox Code Playgroud)

附加信息

UseFilters使用 Express 中的 Response 类可以正常工作,但如果存在任何输入验证错误(使用和) ,我希望能够以 JSON 形式进行响应UsePipes

async generatePDFFile(@Body() inputs: PDFInputsDTO, @Res() response: Response) {
  try {
    const pdfFile = await this.pdfService.generatePDF(inputs);

    response.set({ 'Content-Length': pdfFile.length });
    response.end(pdfFile);
  } catch (e)
    throw e;
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的方法有效,但我失去了像 JSON 对象一样自动响应任何输入验证错误的能力。