title: NestJS: return PDF file from Buffer using StreamableFile
body: <p>I'm using NestJS <code>8.0.2</code> and I'm trying to return a PDF from an API endpoint using the new <a href="https://docs.nestjs.com/techniques/streaming-files" rel="nofollow noreferrer">StreamableFile</a> class which, as the documentation says:</p>
  <blockquote>
  <p>A StreamableFile is a class that holds onto the stream that is to be returned. To create a new StreamableFile, you can pass either a Buffer or a Stream to the StreamableFile constructor.</p>
  </blockquote>
  <p>I'm using a PDF printing library called pdfMake, which provides an option to return the PDF from memory as a <code>Buffer</code> object. I'm trying to avoid saving the generated PDF to the filesystem if possible and just return it directly.</p>
  <p>So I'm trying to combine the two by doing the following:</p>
  <p><strong>pdf-service.ts</strong></p>
  <pre><code>async generatePDF(inputs: PDFInputsDTO) {
    try {
      const definition = this.generateDocDefinition(inputs);
      const document = pdfMake.createPdf(definition);
      const promise = new Promise((resolve, reject) =&gt; {
        try {
          document.getBuffer((result) =&gt; {
            resolve(result); // result is of type Buffer
        } catch (e) {
          reject(e);
        }
      });
  
      return promise as Promise&lt;Buffer&gt;;
    } catch (e) {
      throw new InternalServiceException('PDF generation error');
    }
  }
  </code></pre>
  <p><strong>pdf-controller.ts</strong></p>
  <pre><code>@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 &quot;PDF is: &lt;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 ... &gt;&quot;
  
      return new StreamableFile(pdfFile);
    } catch(e) {
      throw(e);
    }
  }
  </code></pre>
  <p>This results in an exception:</p>
  <pre><code>[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
  </code></pre>
  <p><strong>ADDITIONAL INFO</strong></p>
  <p>Using the Response class from express works, but I want to be able to respond as JSON if there are any input validation errors (using <code>UseFilters</code> and <code>UsePipes</code>):</p>
  <pre><code>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;
    }
  }
  </code></pre>
  <p>The above works, but I lose the ability to automatically respond with any input validation errors as as JSON object.</p>