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

Select.HtmlToPdf IIS部署后不保存PDF仅显示源页面问题排查

Select.HtmlToPdf IIS部署后流程中断、直接展示源页面问题排查方案

问题表现

  • 预期逻辑:后台静默拉取指定HTML页面生成PDF,完成文件保存、邮件发送、数据库更新后跳转至列表页,全程不向用户暴露待转换的源HTML页面
  • Visual Studio开发环境运行完全符合预期
  • IIS生产环境异常:直接向用户返回FactuurPDF源页面,后续PDF保存、邮件发送、数据库更新、页面跳转逻辑全部中止

核心实现代码如下:

// other stuff

HtmlToPdf converter = new HtmlToPdf();
var TxtUrl = "";
TxtUrl = "https://localhost:44368/Facturen/FactuurPDF" + "?id=" + id + "&fact=" + fact;

PdfDocument doc = converter.ConvertUrl(TxtUrl);             
var dat = DateTime.Today.ToString("yyyy-MM-dd");
doc.Save(@Path.Combine(_env.WebRootPath, "Verzondenfacturen/Fact_" + id + "_" + dat + ".pdf"));
doc.Close();

//other stuff (email pdf and update database)
return LocalRedirect("/Facturen/Index");

排查思路

按优先级从高到低排查以下问题点:

  • 硬编码转换地址错误:代码中写死的https://localhost:44368是VS启动IIS Express分配的本地调试端口,生产环境IIS不会监听这个端口。Select.HtmlToPdf内部通过HTTP请求拉取待转换页面,请求不存在的地址会触发请求异常,若全局异常配置不当会直接返回路由匹配到的FactuurPDF页面,中断后续流程。
  • 应用程序池权限不足:Select.HtmlToPdf依赖内置WebKit内核渲染页面,需要启动独立子进程,默认IIS应用程序池使用的ApplicationPoolIdentity身份权限极低,既没有启动渲染进程的权限,也没有写入Verzondenfacturen目录的权限,会在转换或保存步骤抛出未捕获异常。
  • 平台目标不匹配:如果项目编译配置勾选了「32位优先」,但IIS应用程序池未开启「启用32位应用程序」,或者反过来,会导致组件加载失败直接抛出异常。
  • 源页面鉴权拦截:如果FactuurPDF页面需要登录认证才能访问,Select.HtmlToPdf默认发起的请求不带当前用户的认证Cookie,生产环境若开启了身份认证,组件拉取到的是登录页或302跳转响应,部分版本的组件遇到这类非200响应会直接把响应内容回传给客户端,表现为直接展示源页面/登录页。
  • 缺失异常捕获:现有代码没有任何异常处理逻辑,转换、保存任意步骤抛出异常时,若全局异常过滤配置了自动返回当前路由关联的页面结果,就会出现直接展示源页的现象。

可行修复方案

  • 替换硬编码地址:通过当前HTTP请求上下文动态拼接站点可访问地址,不要写死调试用的localhost端口。
  • 配置IIS运行环境:
    • 将对应站点的应用程序池托管管道模式设为集成模式
    • 应用程序池高级设置中把「加载用户配置文件」设为True
    • 匹配平台位数:和项目编译目标一致,设置应用程序池「启用32位应用程序」为对应状态
    • 给站点下的Verzondenfacturen目录添加IIS_IUSRS用户组的读写、修改权限
  • 补充鉴权凭据传递:如果源页面需要登录访问,手动将当前请求的Cookie头传给转换器,避免被鉴权拦截。
  • 补充异常捕获和目录检查逻辑:转换前先确保保存目录存在,捕获转换流程的异常并记录日志,方便定位生产环境具体报错。

修正后参考代码

// other stuff
try
{
    HtmlToPdf converter = new HtmlToPdf();
    // 动态拼接当前站点可访问地址,替换硬编码的调试地址
    var currentRequest = HttpContext.Request;
    var siteBase = $"{currentRequest.Scheme}://{currentRequest.Host}{currentRequest.PathBase}";
    var convertUrl = $"{siteBase}/Facturen/FactuurPDF?id={id}&fact={fact}";

    // 源页面需要鉴权时,传递当前用户的认证Cookie
    converter.Options.HttpCookies = currentRequest.Headers["Cookie"].ToString();

    PdfDocument doc = converter.ConvertUrl(convertUrl);             
    var dateStr = DateTime.Today.ToString("yyyy-MM-dd");
    var saveDir = Path.Combine(_env.WebRootPath, "Verzondenfacturen");
    // 自动创建不存在的保存目录
    Directory.CreateDirectory(saveDir);
    var savePath = Path.Combine(saveDir, $"Fact_{id}_{dateStr}.pdf");
    doc.Save(savePath);
    doc.Close();

    //other stuff (email pdf and update database)
}
catch (Exception ex)
{
    // 此处添加异常日志记录逻辑,生产环境可精准定位报错点
    throw;
}
return LocalRedirect("/Facturen/Index");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:21:14