c# - 从 .net core Web API 下载 PDF 的 Angular
我已经为此挣扎了好几天。我在 Stackoverflow 上找到了许多帖子,但没有一个能解决我的问题。
我有以下 Web API,它应该返回一个简单的 PDF 文件:
[HttpGet("pdf/{id}")]
public async Task<IActionResult> GetOrderAsPDF([FromRoute] int id)
{
MemoryStream ms = new MemoryStream();
PdfWriter writer = new PdfWriter(ms);
PdfDocument pdf = new PdfDocument(writer);
writer.SetCloseStream(false);
Document document = new Document(pdf);
Paragraph header = new Paragraph("HEADER")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(20);
document.Add(header);
document.Close();
ms.Position = 0;
return File(ms, "application/pdf", "test.pdf");
}
service.ts
async getOrderPDF(id):Promise<Blob>{
const url = `${this.baseUrl}/orders/pdf/${id}`;
const key: string = await this.getKey();
console.log('key:', key);
let headers = new HttpHeaders();
headers = headers.append('Authorization', [key]);
return this.http.get(url, {responseType: 'blob', headers: headers}).toPromise();
}
组件.ts
exportPDF(div_id: string){
this.backhausService.getOrderPDF(2).then(x => {
var newBlob = new Blob([x], { type: "application/pdf" });
console.log(newBlob);
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
link.href = data;
link.download = "Test.pdf";
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
});
}
这段代码保存了文件“Test.pdf”,但我无法打开它。它显示“无法加载 PDF 文档”。当我用 Notepad++ 打开该文件时,它显示的是以 Base64 编码的 PDF 文件。Test.pdf 的内容
JVBERi0xLjcKJeLjz9MKNSAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDU2Pj5zdHJlYW0KeJwr5HIK4dJ3M1QwMlAISeMyMjXVszBWMLcw0LOwUAhJ4dLwcHV0cQ3SDMnicg3hCuQCAPm7ClwKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8L0NvbnRlbnRzIDUgMCBSL01lZGlhQm94WzAgMCA1OTUgODQyXS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDYgMCBSPj4+Pi9UcmltQm94WzAgMCA1OTUgODQyXS9UeXBlL1BhZ2U+PgplbmRvYmoKMSAwIG9iago8PC9QYWdlcyAyIDAgUi9UeXBlL0NhdGFsb2c+PgplbmRvYmoKMyAwIG9iago8PC9DcmVhdGlvbkRhdGUoRDoyMDIwMTAyNjA5Mzg1NiswMCcwMCcpL01vZERhdGUoRDoyMDIwMTAyNjA5Mzg1NiswMCcwMCcpL1Byb2R1Y2VyKGlUZXh0riA3LjEuMTMgqTIwMDAtMjAyMCBpVGV4dCBHcm91cCBOViBcKEFHUEwtdmVyc2lvblwpKT4+CmVuZG9iago2IDAgb2JqCjw8L0Jhc2VGb250L0hlbHZldGljYS9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvU3VidHlwZS9UeXBlMS9UeXBlL0ZvbnQ+PgplbmRvYmoKMiAwIG9iago8PC9Db3VudCAxL0tpZHNbNCAwIFJdL1R5cGUvUGFnZXM+PgplbmRvYmoKeHJlZgowIDcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMjcwIDAwMDAwIG4gCjAwMDAwMDA1NjEgMDAwMDAgbiAKMDAwMDAwMDMxNSAwMDAwMCBuIAowMDAwMDAwMTM3IDAwMDAwIG4gCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDQ3MyAwMDAwMCBuIAp0cmFpbGVyCjw8L0lEIFs8MDY0YjIxMjQwNmY5Y2FlMmNiMWVjNzgyM2ZmNzkwNjQ+PDA2NGIyMTI0MDZmOWNhZTJjYjFlYzc4MjNmZjc5MDY0Pl0vSW5mbyAzIDAgUi9Sb290IDEgMCBSL1NpemUgNz4+CiVpVGV4dC03LjEuMTMgZm9yIC5ORVQKc3RhcnR4cmVmCjYxMgolJUVPRgo=
那么我做错了什么?提前感谢你的帮助。
更新
这是我在 Chrome 开发者工具中 API 调用响应的截图。
答案#1
你能尝试一下 @joseph 的答案,并做一点小改动吗?
我已经用你的数据验证过了,一切正常。导入 FileSaver
import * as FileSaver from 'file-saver';
然后
exportPDF(div_id: string){
this.backhausService.getOrderPDF(2).then(data => {
const byteCharacters = atob(data);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], {type: "application/pdf"});
FileSaver.saveAs(blob, 'test.pdf');
});
}
希望它对你也有用。这是使用你的数据的有效示例。https://stackblitz.com/edit/angular-7-master-v7ehpv?file=src/app/app.component.html
关于 Base64 转 blob 的更多信息 https://stackoverflow.com/a/16245768/6310485
答案#2
感谢你的所有帮助。我终于解决了这个问题。
我在问题中没有写出来的,是因为我不知道它是否相关,那就是我正在使用 AWS API Gateway。问题就在这里,因为 API Gateway 需要配置以支持二进制。请参阅 AWS 文档。
由于我希望 API 尽可能简单,我已将代码更改如下,以返回带引号的 Base64 编码文件。
API端点
[HttpGet("pdf/{id}")]
public async Task<IActionResult> GetOrderAsPDF([FromRoute] int id)
{
MemoryStream ms = new MemoryStream();
PdfWriter writer = new PdfWriter(ms);
PdfDocument pdf = new PdfDocument(writer);
writer.SetCloseStream(false);
Document document = new Document(pdf);
Paragraph header = new Paragraph("HEADER")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(20);
document.Add(header);
document.Close();
ms.Position = 0;
return Ok(ms.GetBuffer());
}
服务.ts
async getOrderPDF(id):Promise<string>{
const url = `${this.baseUrl}/orders/pdf/${id}`;
const key: string = await this.getKey();
let headers = new HttpHeaders();
headers = headers.append('Authorization', [key]);
return this.http.get<string>(url, {headers}).pipe(catchError(this.handleError<string>('getOrdersCustomer'))).toPromise();
}
组件.ts
exportPDF(div_id: string){
this.backhausService.getOrderPDF(2).then(x => {
console.log(x);
const data = `data:application/pdf;base64,${x}`;
var link = document.createElement('a');
link.href = data;
link.download = "test.pdf";
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
});
}
通过对后端代码的更改,API 调用的响应如下。

