You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Angular从基于iTextSharp的C# API下载PDF文件

修复C# API并实现Angular获取PDF的方案

一、C# API代码的问题修复

存在的核心问题:

  • PDF生成路径错误:直接在当前目录创建文件,后续却去wwwroot/docs查找,必然找不到目标文件
  • 服务器端调用Process.Start:这会在服务器本地打开PDF,客户端完全无法感知,毫无实际意义
  • 资源未正确释放:FileStream未使用using语句自动释放,可能导致文件占用或泄漏
  • 异步方法未落地:方法标记为async但无任何异步操作,要么移除async,要么改用异步IO
  • 未利用doacaoId参数:当前代码未根据捐赠ID获取数据填充PDF内容,逻辑不完整
  • 返回值错误:返回CustomResponse无法让客户端接收到PDF文件,需返回文件流类型

修复后的API代码:

[AllowAnonymous]
[HttpGet("comprovante-pdf/{doacaoId:guid}")]
public IActionResult GerarComprovantePdf(Guid doacaoId)
{
    // 1. 先根据doacaoId查询数据库获取捐赠数据(示例省略,需自行补充业务逻辑)
    // var doacao = await _doacaoRepository.GetByIdAsync(doacaoId);
    // if (doacao == null) return NotFound("捐赠记录不存在");

    var pxPorMm = 72 / 25.2F;
    var pdf = new Document(PageSize.A4.Rotate(), 15 * pxPorMm, 15 * pxPorMm, 15 * pxPorMm, 20 * pxPorMm);
    
    // 直接在wwwroot/docs目录创建文件,确保路径正确
    var fileName = $"comprovante_vaquinha_animal.{DateTime.Now:dd.MM.yyyy.HH.mm}.pdf";
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/docs", fileName);

    // 使用using自动释放FileStream资源
    using var arquivo = new FileStream(filePath, FileMode.Create);
    var writer = PdfWriter.GetInstance(pdf, arquivo);
    pdf.Open();

    // 添加标题
    var fonteTitulo = new Font(fonteBase, 28, Font.NORMAL, BaseColor.Black);
    var titulo = new Paragraph("Comprovante de Doação", fonteTitulo);
    titulo.Alignment = Element.ALIGN_LEFT;
    titulo.SpacingAfter = 10;
    pdf.Add(titulo);

    // 添加表格(填充实际捐赠数据)
    var tabela = new PdfPTable(4);
    float[] largurasColunas = { 0.5f, 1.5f, 1.0f, 1.2f };
    tabela.SetWidths(largurasColunas);
    tabela.DefaultCell.BorderWidth = 0;
    tabela.WidthPercentage = 100;

    // 示例:插入捐赠数据行(替换为实际业务数据)
    tabela.AddCell("ID");
    tabela.AddCell(doacaoId.ToString());
    tabela.AddCell("Data");
    tabela.AddCell(DateTime.Now.ToString("dd/MM/yyyy"));

    pdf.Add(tabela);
    pdf.Close();

    // 返回PDF文件流给客户端,指定文件名触发浏览器下载
    var fileBytes = System.IO.File.ReadAllBytes(filePath);
    return File(fileBytes, "application/pdf", fileName);
}

二、Angular端获取并下载PDF的实现

1. 封装API调用服务

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class DoacaoService {
  private apiBaseUrl = '你的API基础地址'; // 替换为实际API地址

  constructor(private http: HttpClient) {}

  gerarComprovantePdf(doacaoId: string) {
    const headers = new HttpHeaders({
      'Accept': 'application/pdf'
    });

    return this.http.get(`${this.apiBaseUrl}/comprovante-pdf/${doacaoId}`, {
      headers,
      responseType: 'blob' // 指定返回类型为二进制Blob
    });
  }
}

2. 组件中触发下载逻辑

import { Component } from '@angular/core';
import { DoacaoService } from './doacao.service';

@Component({
  selector: 'app-doacao',
  templateUrl: './doacao.component.html'
})
export class DoacaoComponent {
  constructor(private doacaoService: DoacaoService) {}

  baixarComprovante(doacaoId: string) {
    this.doacaoService.gerarComprovantePdf(doacaoId).subscribe(blob => {
      // 创建Blob临时URL
      const url = window.URL.createObjectURL(blob);
      // 创建隐藏a标签触发下载
      const downloadLink = document.createElement('a');
      downloadLink.href = url;
      downloadLink.download = `comprovante_vaquinha_animal.pdf`; // 自定义下载文件名
      document.body.appendChild(downloadLink);
      downloadLink.click();
      // 释放资源并清理DOM元素
      window.URL.revokeObjectURL(url);
      document.body.removeChild(downloadLink);
    }, error => {
      console.error('生成PDF失败:', error);
      alert('无法生成捐赠证明,请稍后重试');
    });
  }
}

3. 模板添加触发按钮

<button (click)="baixarComprovante('你的捐赠ID')">下载捐赠证明</button>

内容的提问来源于stack exchange,提问作者ThiagoWerneck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:37:35