首页 > 解决方案 > NestJS:使用 StreamableFile 从 Buffer 返回 PDF 文件

问题描述

我正在使用 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');
  }
}

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);
  }
}

这会导致异常:

[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

附加信息

UseFilters使用 express 中的 Response 类,但如果有任何输入验证错误(使用and UsePipes),我希望能够以 JSON 响应:

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;
  }
}

以上方法有效,但我失去了将任何输入验证错误作为 JSON 对象自动响应的能力。

标签: node.jstypescriptnestjs

解决方案


推荐阅读