如何在Chrome/Edge浏览器中点击按钮实现SSRS报告打印
问题根因
你遇到的Not allowed to load local resource报错本质是浏览器安全沙箱限制,所有现代浏览器都禁止网页直接加载本地磁盘file://协议的资源,和文件夹权限无关,这个限制是为了防止恶意网页窃取用户本地文件,无法绕过。你之前动态赋值iframe src为空、硬编码路径无效的问题也和这个限制直接相关。
修复方案
步骤1:调整PDF存储路径
不要把生成的PDF存在网站根目录以外的本地磁盘路径,在你的Web应用根目录下新建一个临时目录,比如命名为TempPDF,给这个目录授予IIS运行账号(通常是IIS_IUSRS)的读写权限即可,不需要开放Everyone权限,避免安全风险。
注意:建议给每个生成的PDF分配唯一文件名(比如用
Guid.NewGuid().ToString() + ".pdf"命名),避免多用户同时操作时文件被覆盖冲突。
步骤2:修改服务端代码
修改BtnPrint_Click逻辑,将PDF写入Web应用的TempPDF目录,同时给iframe的src赋值为PDF的Web可访问路径,而非本地磁盘路径:
private void BtnPrint_Click(object sender, EventArgs e) { Warning[] warnings; string[] streamids; string mimeType; string encoding; string extension; byte[] bytes = ReportViewer1.ServerReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamids, out warnings); // 生成唯一文件名 string fileName = Guid.NewGuid().ToString() + ".pdf"; // 拼接本地物理路径 string localPath = Path.Combine(Server.MapPath("~/TempPDF"), fileName); using (FileStream fs = new FileStream(localPath, FileMode.Create)) { fs.Write(bytes, 0, bytes.Length); } // 拼接Web可访问的相对路径 string webPath = $"/TempPDF/{fileName}"; frmPrint.Attributes["src"] = webPath; ScriptManager.RegisterStartupScript(Page, this.GetType(), "printReport", $"printReport('{webPath}');", true); }
步骤3:修改前端JS逻辑
你之前的代码赋值src后立即调用打印,会出现PDF还未加载完成就触发打印的问题,需要监听iframe的加载完成事件后再调用打印:
function printReport(pdfPath) { var iframe = document.getElementById('frmPrint'); // 先绑定加载完成事件,再赋值src iframe.onload = function() { var frm = iframe.contentWindow; frm.focus(); frm.print(); // 可选:打印完成后调用接口删除临时PDF,或者后台做定时清理任务 }; iframe.src = pdfPath; return true; }
可选优化方案(无需存本地文件)
如果不想生成临时文件,可以新增一个PrintPDF.ashx一般处理程序,直接将PDF字节流返回给前端,iframe的src直接指向这个处理程序即可,避免本地文件存储和清理的问题。
内容的提问来源于stack exchange,提问作者Raja Sekhar
相关产品推荐
相关产品推荐

