SSRS 导出经无客户端 VPN 门户失败:差异在哪里
报表页面证明的是渲染,不是导出。沿门户追踪导出请求,比较响应头与正文,然后把例外范围收窄。
报表在浏览器中打开,参数正常渲染,导出按钮却返回错误、空下载,或生成一个电子表格拒绝打开的文件。这一组合有标准形态。能打开的报表页只验证了渲染与身份验证,别的都没有。导出是另一个请求,有自己的响应;经无客户端门户时,它还要穿过一层从未为文件下载设计的改写层。
两条路径,一个能用的页面
渲染与导出是两种操作,即使它们从同一个按钮开始。报表服务器为浏览器渲染页面,而导出经由另一种输出扩展渲染,有自己的内容类型和错误行为,正如导出文档所述。门户能完美放行前者,仍可能弄坏后者,因为后者是门户没料到会看到的响应。两者共享一个会话和一个地址,几乎没有别的共同点。
只把能用的页面当作身份验证与可达性的证据。它证明账户能到达报表服务器,门户会转发 HTML。它对文件响应、内容处置响应头,或以下载而非文档收尾的重定向一无所知。
正因如此,应当单独比较导出路径,而不是反复测试已经能打开的页面。共享会话的两个请求仍然是两个请求。
决定导出在何处断裂的三个条件
三个问题能迅速定位故障,每个答案指向不同的责任方。
第一,同一报表、账户和格式从内网导出是否正常?如果正常,报表服务器及其渲染器没有问题,差异出在访问路径上。第二,失败的响应带的是文件内容类型,还是套着文件扩展名的 HTML 页面?这能把渲染器错误与门户替换区分开。第三,门户是否改写请求 URL,或剥掉响应头?被改写的 URL 可能落到完全不同的端点。
改任何设置之前先回答这三个问题,因为每个的补救方式都不同。渲染器故障属于报表服务器,被替换的正文属于门户,被剥掉的响应头是策略问题而不是缺陷。
把答案写下来。用这三行搭出的支持工单,抵得上十张截图。
读导出响应,而不是只看状态码
HTTP 成功状态只能证明有东西回应了请求。要把正文和响应头一起检查,因为真正值得注意的失败是成功的响应带着错误的内容。
curl -sS -D export.headers -o export.bin --location "https://portal.example.com/reports/export?format=xlsx"
file export.bin
head -c 300 export.bin
响应头转储会显示内容类型,以及门户返回的任何内容处置。file 命令能判定正文到底是什么,而在本该是电子表格的地方出现文本文件,就是典型的被替换的登录页。head 命令足以辨认 HTML,又不会把整份报表倒进终端。
分享之前先删掉会话 Cookie 和令牌。对可用导出的抓包是有用证据,对别人会话的抓包则是事故。
把例外限定在应用上,而不是账户上
如果门户在改写或拦截响应,诱人的修法是豁免整个站点,或把报表改成匿名。两者都能修好下载,却抹掉了门户存在的理由。范围收窄的例外会指明一条应用路径、一种内容类型和一个方向,并且始终可被策略所有者复核。
使用你实际运行的网关版本及其有文档的应用设置。厂商曾经描述为“保持流量不变”的选项并不是通用指令,从旧论坛帖子里照抄,正是临时例外变成永久架构的方式。
如果例外无法收得这么窄,导出大概更适合放在内网路径上换一种访问方式,而不是放在门户后面。整站豁免是门户所有者的决定,不是为一份报表开的旁路。
验收导出,而不是验收保存对话框
最后一项检查是文件本身:能打开、含预期列,合计与用户批准的报表一致。
出现保存对话框不算成功,打开时带修复警告的文件也不算成功。把行数和至少一个已知值与屏幕上的报表对照,因为被截断的导出能通过所有只看文件大小的测试。然后再导出一次,因为一次返回错误正文的缓存层,下一次可能返回正确的。
接受用户真正需要的工作流,一点都不能少。在错误的应用里打开的下载,仍然是失败的导出。