【问题标题】:Angular download PDF from .net core web api从.net core web api角度下载PDF
【发布时间】:2020-10-26 09:48:27
【问题描述】:

我已经为此苦苦挣扎了几天。我在 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();
}

component.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++ 打开文件时,它会显示 PDF 文件为 Base64 编码字符串。 Test.pdf的内容

JVBERi0xLjcKJeLjz9MKNSAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDU2Pj5zdHJlYW0KeJwr5HIK4dJ3M1QwMlAISeMyMjXVszBWMLcw0LOwUAhJ4dLwcHV0cQ3SDMnicg3hCuQCAPm7ClwKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8L0NvbnRlbnRzIDUgMCBSL01lZGlhQm94WzAgMCA1OTUgODQyXS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDYgMCBSPj4+Pi9UcmltQm94WzAgMCA1OTUgODQyXS9UeXBlL1BhZ2U+PgplbmRvYmoKMSAwIG9iago8PC9QYWdlcyAyIDAgUi9UeXBlL0NhdGFsb2c+PgplbmRvYmoKMyAwIG9iago8PC9DcmVhdGlvbkRhdGUoRDoyMDIwMTAyNjA5Mzg1NiswMCcwMCcpL01vZERhdGUoRDoyMDIwMTAyNjA5Mzg1NiswMCcwMCcpL1Byb2R1Y2VyKGlUZXh0riA3LjEuMTMgqTIwMDAtMjAyMCBpVGV4dCBHcm91cCBOViBcKEFHUEwtdmVyc2lvblwpKT4+CmVuZG9iago2IDAgb2JqCjw8L0Jhc2VGb250L0hlbHZldGljYS9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvU3VidHlwZS9UeXBlMS9UeXBlL0ZvbnQ+PgplbmRvYmoKMiAwIG9iago8PC9Db3VudCAxL0tpZHNbNCAwIFJdL1R5cGUvUGFnZXM+PgplbmRvYmoKeHJlZgowIDcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMjcwIDAwMDAwIG4gCjAwMDAwMDA1NjEgMDAwMDAgbiAKMDAwMDAwMDMxNSAwMDAwMCBuIAowMDAwMDAwMTM3IDAwMDAwIG4gCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDQ3MyAwMDAwMCBuIAp0cmFpbGVyCjw8L0lEIFs8MDY0YjIxMjQwNmY5Y2FlMmNiMWVjNzgyM2ZmNzkwNjQ+PDA2NGIyMTI0MDZmOWNhZTJjYjFlYzc4MjNmZjc5MDY0Pl0vSW5mbyAzIDAgUi9Sb290IDEgMCBSL1NpemUgNz4+CiVpVGV4dC03LjEuMTMgZm9yIC5ORVQKc3RhcnR4cmVmCjYxMgolJUVPRgo=

那我做错了什么? 提前感谢您的贡献。

更新

这是我从 chrome 开发工具获取的 api 调用响应的屏幕截图。

【问题讨论】:

  • 将生成的PDF文件保存到磁盘,并将PDF文件的URL发送到UI下载
  • 我正在使用无服务器方法,Web api 在 Lambda 函数中运行。所以这不是我喜欢的方式。
  • 我也遇到过类似的问题,但是xlsx 文件。我将生成的文件上传到 Azure 存储并返回存储文件的 URL。
  • 您可以尝试使用 'file-saver' 包 (npm) 提供的 'saveAs' 功能。从 getOrderPDF() 调用获得结果后,您可以调用 'saveAs(new Blob([x], { type: "application/pdf" }), 'Test.pdf)' 将文件保存到本地。
  • 感谢您的方法。我刚刚对其进行了测试,但它仍然无法正常工作。和以前一样的问题。

标签: c# angular typescript


【解决方案1】:

你能稍微改变一下@joseph 的答案吗?

我已使用您的数据进行了验证。它工作正常。 导入文件保护程序

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 网关。这就是问题所在,因为 API Gateway 需要配置为支持 binay。请参阅aws docs

    因为我想让 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());
    }
    

    Service.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();
    }
    

    Component.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调用响应如下所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-20
      • 2020-10-10
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 2018-05-08
      • 2018-04-23
      • 2021-09-24
      相关资源
      最近更新 更多