从 NestJS 下载文件(不保存)

Download a file from NestJS (without saving it )

我想让客户端下载从我的后端生成的 pdf 文件。我正在使用 pdfkit-lib to generate my pdf file. From the NestJs documentation,我决定使用 DuplexStream 中的 StreamableFile(pdfkit-lib 使用 WritableStreamStreamableFile 使用 ReadableStream) :

@Get('/generate-file')
generateFile(): StreamableFile {
  const fileStream = new stream.Duplex();
  const doc = new pdfkit()
  doc.pipe(fileStream);
  // do stuff
  doc.end();
  return new StreamableFile(fileStream);
}

但我最终遇到了这个错误:

Error: The _write() method is not implemented
    at new NodeError (node:internal/errors:371:5)
    at Duplex.Writable._write (node:internal/streams/writable:588:11)
    at writeOrBuffer (node:internal/streams/writable:389:12)
    at _write (node:internal/streams/writable:330:10)
    at Duplex.Writable.write (node:internal/streams/writable:334:10)
    at PDFDocument.ondata (node:internal/streams/readable:754:22)
    at PDFDocument.emit (node:events:390:28)
    at PDFDocument.Readable.read (node:internal/streams/readable:527:10)
    at flow (node:internal/streams/readable:1012:34)
    at resume_ (node:internal/streams/readable:993:3)

它可以与 fs.createWriteStreamfs.createReadStream 一起使用,但我不想在我的服务器上创建该文件(并且 StreamableFile 上没有要删除的回调)。有什么想法吗?

我最终通过删除创建的文件使用 fs.createWriteStreamfs.createReadStream :

@Get('/generate-file')
generateFile(): StreamableFile {
  const filePath = '';

  const doc = new pdfkit()
  doc.pipe(fs.createWriteStream(filePath));
  // do stuff
  doc.end();

  const fileStream = fs.createReadStream(filePath);

  fileStream.on('end', () => {
    try {
      fs.unlinkSync(filePath);
    } catch (error) {
      throw new BadRequestException('An error occurred while removing the file.');
    }
  });
  return new StreamableFile(fileStream);
}

应该可以在没有写入临时文件的开销的情况下执行此操作。您可以尝试直接流式传输到 res 流中,例如:

@Get('/generate-file')
generateFile(@Res() res: Response): void {
   const filename = 'SomeFileName.pdf';
   const doc = new PDFDocument({ bufferPages: true });
   const stream = res.writeHead(200, {
    'Content-Type': 'application/pdf',
    'Content-disposition': `attachment;filename=${filename}.pdf`,
   });
   doc.on('data', (chunk) => stream.write(chunk));
   doc.on('end', () => stream.end());

   doc
     .font('Times-Roman')
     .fontSize(12)
     .text(`just a test`);
   doc.end();
 }