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

ASPX页面PDF下载后无法跳转至指定页面的技术问题

解决ASP.NET PDF下载后无法重定向的问题

这个问题的核心原因很明确:在同一个HTTP响应里,你既输出了PDF文件内容,又试图添加重定向/刷新头,这两者是冲突的。浏览器在处理下载响应时,只会专注于接收文件,不会去解析执行Refresh这类跳转指令;而且当你通过Response.OutputStream写入PDF内容后,响应的主体已经被占用,后续的Response操作(包括添加头)都无法正确生效。

下面给你两种可行的解决方案:

方案一:前端JavaScript触发下载+延迟跳转

这是最可靠的方案,把下载和跳转的逻辑拆分到前端处理:

  1. 修改服务器端的按钮点击事件,不要直接输出PDF,而是先把PDF保存到服务器的临时目录(或者生成一个可访问的下载链接),然后返回一个提示页面,用JS来完成后续操作。

修改后的后台代码示例:

protected void buttSubmit_Click(object sender, EventArgs e)
{
    if (intInvoID > 0) { UpdateInvoice(); } 
    else { SaveInvoice(); } 

    // 生成PDF到临时文件,而不是直接输出到Response
    string tempPdfPath = Server.MapPath("~/Temp/") + "Invoice_" + txtCompanyName.Text.Trim() + ".pdf";
    GeneratePdfToFile(strheader, htrFooter, strContact, strExihibition, strPaymentDetails, strNotes, tempPdfPath);

    // 跳转到一个中间页面,由JS处理下载和跳转
    Response.Redirect($"~/DownloadAndRedirect.aspx?pdfPath={tempPdfPath}&redirectUrl=~/expo_crm/invoice/View_Invoices.aspx");
}

// 新增生成PDF到文件的方法
private void GeneratePdfToFile(string strheader, string strFooter, string strContact, string strExihibition, string strPaymentDetails, string strNotes, string outputPath)
{
    using (var fs = new FileStream(outputPath, FileMode.Create))
    {
        Document pdfDocument = new Document(PageSize.A4, 40f, 40f, 15f, 2f);
        PdfWriter pdfDoc1 = PdfWriter.GetInstance(pdfDocument, fs);
        var page = new ITextEvents();
        page.email = txtExpogrEmail.Text.Trim();
        pdfDoc1.PageEvent = page;
        pdfDocument.Open();
        pdfDocument.Add(ph1);
        pdfDocument.Add(tblBlank);
        pdfDocument.Add(tblAddInfo);
        pdfDocument.Add(tblCon);
        pdfDocument.Add(tblExhibition);
        pdfDocument.Add(tblNotes);
        pdfDocument.Add(iHeader);
        pdfDocument.Add(jpg);
        pdfDocument.Add(jpg1);
        
        StringReader srHtmlText = new StringReader(sbHtmlText.ToString());
        iTextSharp.text.html.simpleparser.HTMLWorker htmlparser = new iTextSharp.text.html.simpleparser.HTMLWorker(pdfDocument);
        htmlparser.Parse(srHtmlText);
        
        pdfDocument.Close();
    }
}
  1. 创建DownloadAndRedirect.aspx页面,在其Page_Load里添加前端脚本:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DownloadAndRedirect.aspx.cs" Inherits="DownloadAndRedirect" %>
<!DOCTYPE html>
<html>
<head>
    <title>处理中...</title>
    <script>
        window.onload = function() {
            // 触发PDF下载
            const downloadLink = document.createElement('a');
            downloadLink.href = '<%= ResolveUrl("~/DownloadTempPdf.ashx?file=" + Server.UrlEncode(Request.QueryString["pdfPath"])) %>';
            downloadLink.download = '<%= Path.GetFileName(Request.QueryString["pdfPath"]) %>';
            downloadLink.click();
            
            // 延迟2秒后跳转到目标页面,给浏览器足够时间处理下载
            setTimeout(() => {
                window.location.href = '<%= ResolveUrl(Request.QueryString["redirectUrl"]) %>';
            }, 2000);
        }
    </script>
</head>
<body>
    <p>正在准备您的PDF文件,稍后将自动跳转...</p>
</body>
</html>
  1. 创建DownloadTempPdf.ashx一般处理程序,负责输出临时PDF文件并清理:
public class DownloadTempPdf : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string filePath = context.Request.QueryString["file"];
        if (File.Exists(filePath))
        {
            context.Response.ContentType = "application/pdf";
            context.Response.AddHeader("content-disposition", $"attachment;filename={Path.GetFileName(filePath)}");
            context.Response.WriteFile(filePath);
            // 下载完成后删除临时文件(可选,也可以定时清理)
            File.Delete(filePath);
        }
        else
        {
            context.Response.Write("文件不存在");
        }
    }

    public bool IsReusable => false;
}

方案二:用iframe加载PDF,当前页面直接跳转

这种方案更简洁,但要注意浏览器的下载拦截设置:

直接在按钮点击的前端事件里处理(可以把按钮改成客户端触发):

<asp:Button ID="buttSubmit" runat="server" Text="Submit" OnClientClick="startDownloadAndRedirect(); return false;" />
<script>
function startDownloadAndRedirect() {
    // 创建隐藏iframe加载PDF生成页面
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = '<%= ResolveUrl("~/GeneratePdf.aspx") %>'; // 这个页面就是原来的1.aspx,只负责生成PDF输出
    document.body.appendChild(iframe);
    
    // 直接跳转到目标页面
    setTimeout(() => {
        window.location.href = '<%= ResolveUrl("~/expo_crm/invoice/View_Invoices.aspx") %>';
    }, 1000);
}
</script>

然后修改GeneratePdf.aspx的后台代码,确保正确输出PDF并结束响应:

protected void Page_Load(object sender, EventArgs e)
{
    if (intInvoID > 0) { UpdateInvoice(); } 
    else { SaveInvoice(); } 
    GenearatePDf(strheader, htrFooter, strContact, strExihibition, strPaymentDetails, strNotes);
    Response.End(); // 必须结束响应,避免输出多余内容
}

// 修正原GeneratePdf方法的错误
private void GenearatePDf(string strheader, string strFooter, string strContact, string strExihibition, string strPaymentDetails, string strNotes) 
{ 
    Response.ContentType = "application/pdf"; 
    Response.AddHeader("content-disposition", "attachment;filename=Invoice_" + txtCompanyName.Text.Trim() + ".pdf"); 
    Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    
    Document pdfDocument = new Document(PageSize.A4, 40f, 40f, 15f, 2f); 
    PdfWriter pdfDoc1 = PdfWriter.GetInstance(pdfDocument, Response.OutputStream); 
    var page = new ITextEvents(); 
    page.email = txtExpogrEmail.Text.Trim(); 
    pdfDoc1.PageEvent = page; 
    pdfDocument.Open(); 
    pdfDocument.Add(ph1); 
    pdfDocument.Add(tblBlank); 
    pdfDocument.Add(tblAddInfo); 
    pdfDocument.Add(tblCon); 
    pdfDocument.Add(tblExhibition); 
    pdfDocument.Add(tblNotes); 
    pdfDocument.Add(iHeader); 
    pdfDocument.Add(jpg); 
    pdfDocument.Add(jpg1); 
    
    StringReader srHtmlText = new StringReader(sbHtmlText.ToString()); 
    iTextSharp.text.html.simpleparser.HTMLWorker htmlparser = new iTextSharp.text.html.simpleparser.HTMLWorker(pdfDocument); 
    htmlparser.Parse(srHtmlText); 
    
    pdfDocument.Close(); 
    // 移除Response.Write(pdfDocument); 这行是错误的,PdfWriter已经写入到OutputStream了
}

注意事项

  • 方案一中的临时文件要注意清理,可以定时任务删除过期文件,避免服务器磁盘被占满。
  • 方案二可能被部分浏览器的下载拦截功能阻止,需要用户允许下载。
  • 原代码中Response.Write(pdfDocument);是错误的,因为PdfWriter.GetInstance已经把PDF内容写入到Response.OutputStream了,不需要再Write文档对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:30:17