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

ASP.NET Core MVC:通过Ajax调用Rotativa并在新标签页打开PDF问题

解决ASP.NET Core MVC中通过POST+防伪令牌调用Rotativa导出PDF并新标签页打开的问题

核心问题原因

直接用Ajax接收Rotativa返回的PDF二进制流时,若未指定正确的响应类型,浏览器会将二进制数据解析为文本,导致显示乱码。需要通过Blob处理或动态表单提交两种方式解决。


步骤1:修改控制器方法

将原GET接口改为POST,添加防伪令牌验证,接收复杂参数:

[HttpPost("ExportRotativa")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExportRotativa([FromBody] YourComplexParamModel paramModel)
{
    // 根据传入参数获取报表数据
    DbImpendingMedicareReportViewModel model = await _IfunctionsUtil.ImpendingMedicareElibigibilityReport(paramModel);
    model.uIElementModel = SessionManagerUtil.GetUIElement(HttpContext.Session);

    // 配置PDF导出选项
    var pdfResult = new ViewAsPdf("NewPdf", model)
    {
        FileName = "Medicare_Eligibility_Report.pdf",
        PageSize = Rotativa.AspNetCore.Options.Size.A4
    };

    return pdfResult;
}

说明:

  • YourComplexParamModel是你定义的复杂参数模型类,需与前端传入的参数结构匹配
  • 若使用表单提交而非JSON,可将[FromBody]改为[FromForm],并调整参数接收方式

步骤2:前端实现方案

方案一:Ajax+Blob处理(推荐,支持复杂JSON参数)

通过Ajax请求获取Blob格式的PDF流,创建临时URL在新标签页打开:

<!-- 确保页面包含防伪令牌(ASP.NET Core Razor页面默认自动生成,或手动添加) -->
@Html.AntiForgeryToken()

<button id="exportPdfBtn">导出PDF</button>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
    $('#exportPdfBtn').click(function() {
        // 获取防伪令牌值
        const antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
        
        // 构造复杂参数
        const complexParams = {
            StartDate: $('#StartDate').val(),
            EndDate: $('#EndDate').val(),
            DepartmentIds: [101, 102, 103],
            IncludeInactive: $('#IncludeInactive').is(':checked')
        };

        $.ajax({
            url: '/ExportRotativa',
            type: 'POST',
            headers: {
                'RequestVerificationToken': antiForgeryToken
            },
            data: JSON.stringify(complexParams),
            contentType: 'application/json',
            responseType: 'blob', // 关键:指定响应为二进制Blob
            success: function(blob) {
                // 创建临时URL指向Blob数据
                const pdfUrl = window.URL.createObjectURL(blob);
                // 在新标签页打开PDF
                window.open(pdfUrl);
                // 延迟释放URL资源,避免内存泄漏
                setTimeout(() => window.URL.revokeObjectURL(pdfUrl), 100);
            },
            error: function(xhr) {
                console.error('PDF导出失败:', xhr.responseText);
                alert('导出失败,请检查参数或重试');
            }
        });
    });
</script>

方案二:动态表单提交(兼容旧浏览器,适合简单参数)

通过动态创建隐藏表单提交POST请求,让浏览器直接处理PDF响应:

@Html.AntiForgeryToken()

<button id="exportPdfBtn">导出PDF</button>

<script>
    $('#exportPdfBtn').click(function() {
        const antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
        const complexParams = {
            StartDate: document.getElementById('StartDate').value,
            EndDate: document.getElementById('EndDate').value
        };

        // 创建隐藏表单
        const form = document.createElement('form');
        form.method = 'POST';
        form.action = '/ExportRotativa';
        form.target = '_blank'; // 指定在新标签页打开

        // 添加防伪令牌
        const tokenInput = document.createElement('input');
        tokenInput.type = 'hidden';
        tokenInput.name = '__RequestVerificationToken';
        tokenInput.value = antiForgeryToken;
        form.appendChild(tokenInput);

        // 添加复杂参数(转为JSON字符串提交)
        const paramInput = document.createElement('input');
        paramInput.type = 'hidden';
        paramInput.name = 'paramModel';
        paramInput.value = JSON.stringify(complexParams);
        form.appendChild(paramInput);

        // 提交表单并移除
        document.body.appendChild(form);
        form.submit();
        document.body.removeChild(form);
    });
</script>

对应控制器需调整参数接收:

[HttpPost("ExportRotativa")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExportRotativa([FromForm] string paramModel)
{
    // 解析JSON字符串为参数模型
    var complexParam = System.Text.Json.JsonSerializer.Deserialize<YourComplexParamModel>(paramModel);
    // 后续逻辑同方案一
}

额外注意事项

  1. 确保已正确注册Rotativa服务:在Program.cs中添加builder.Services.AddRotativa();
  2. 若视图中使用了Session,需确保Session配置正确,且控制器方法允许访问Session
  3. 测试时注意浏览器弹窗拦截设置,避免新标签页被拦截

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:34:55