gpt4 book ai didi

javascript - NestJS/Express 从外部 URL 返回 PDF 文件作为响应

转载 作者:行者123 更新时间:2023-12-05 05:40:24 30 4
gpt4 key购买 nike

我正在调用一个返回 PDF 文件的外部 API,我想在我的 Controller 函数响应中返回这个 PDF 文件。

在我的 Controller 类中:

  @Get(':id/pdf')
async findPdf(@Param('id') id: string, @Res() res: Response) {
const response = await this.documentsService.findPdf(id);

console.log(response.data);
// this prints the following:
// %PDF-1.5
// %����
// 2 0 obj
// << /Type /XObject /Subtype /Image /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter // /DCTDecode /Width 626 /Height
// 76 /Length 14780>>
// stream
// and go on...

return res
.status(200)
.header('Content-Type', 'application/pdf')
.header('Content-Disposition', response.headers['content-disposition'])
.send(response.data);
}

在我的服务类中:

  findPdf(id: string): Promise<any> {
return firstValueFrom(
this.httpService
.get(`/docs/${id}/pdf`)
.pipe(map((response) => response))
.pipe(
catchError((e) => {
throw new BadRequestException('Failed to get PDF.');
}),
),
);
}

但是我在回复中收到了一个空白的 PDF 文件。

内部 API 调用工作正常,我已经从 Postman 对其进行了测试,PDF 文件是正确的。

我做错了什么?

最佳答案

我已经测试并重现了您描述的问题。

原因是您的外部服务器以 PDF 作为流进行响应,而您的解决方案未处理它。

首先,由于响应是流,您需要通过更改通知 Axios(HTTP 服务):

.get(`/docs/${id}/pdf`)

到:

.get(`/docs/${id}/pdf`, { responseType: "stream" })

之后,您有两种方法(取决于您的需要):

  1. 您可以将该流通过管道传输到您的主要响应(因此将流传输到您的服务的调用者)。

  2. 您可以从文档服务器收集整个流数据,然后将最终的缓冲区数据传递给调用者。

希望对您有所帮助。

完整的示例代码在这里:

import { HttpService } from "@nestjs/axios";
import { BadRequestException, Controller, Get, Res } from "@nestjs/common";
import { catchError, firstValueFrom, map, Observable } from "rxjs";
import { createReadStream } from "fs";

@Controller('pdf-from-external-url')
export class PdfFromExternalUrlController {

constructor(
private httpService: HttpService
) {
}

// Simulated external document server that responds as stream!
@Get()
async getPDF(@Res() res) {
const file = createReadStream(process.cwd() + '/files/test.pdf');
return file.pipe(res);
}

@Get('indirect-pdf')
async findPdf(@Res() res) {
const pdfResponse = await firstValueFrom(this.httpService
.get(`http://localhost:3000/pdf-from-external-url`, { responseType: "stream" })
.pipe(map((response) => response))
.pipe(
catchError((e) => {
throw new BadRequestException('Failed to get PDF.');
}),
));

// APPROACH (1) - deliver your PDF as stream to your caller
// pdfResponse.data.pipe(res);
// END OF APPROACH (1)

// APPROACH (2) - read whole stream content on server and then deliver it
const streamReadPromise = new Promise<Buffer>((resolve) => {
const chunks = [];
pdfResponse.data.on('data', chunk => {
chunks.push(Buffer.from(chunk));
});
pdfResponse.data.on('end', () => {
resolve(Buffer.concat(chunks));
});
});

const pdfData = await streamReadPromise;

res.header('Content-Type', 'application/pdf')
res.send(pdfData);
// END OF APPROACH (2)
}
}

关于javascript - NestJS/Express 从外部 URL 返回 PDF 文件作为响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72439914/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com