单击 Excel 中的超链接时,资源将被调用三次(如果之前访问过该 URL,则调用两次)。第一次和第二次被隐藏,第三次在浏览器中按预期进行。
细节
我在 Excel 2016 中使用超链接公式,如下所示,但在没有公式而只有超链接功能时也会出现问题:
=HYPERLINK(CONFIRM_NO_DATA_URL&B3)
无论如何,它应该调用这样的 URL
http://example.org/index.php?action=replyToEmailId&emailId=123123123
当我单击该单元格时,将打开一个带有正确 URL 的新选项卡。
但是:该 URL 实际上被调用了三次(我首先注意到了这一点,因为三封电子邮件在短暂延迟后发送)。
我试图通过将 Http-Headers 放入文件中来找出这个问题的来源。结果发现,excel 在浏览器中打开链接之前会在内部调用超链接。此外,提供的 Http-Headers 与最终请求不同。
第一个隐藏请求
这是使用 HEAD Http-Request-Method 的第一个请求:
{
"HTTP_USER_AGENT": "Microsoft Office Excel 2014 (16.0.10730) Windows NT 10.0",
"HTTP_X_OFFICE_MAJOR_VERSION": "16",
"HTTP_X_MS_COOKIEURI_REQUESTED": "t",
"HTTP_X_FEATUREVERSION": "1",
"HTTP_ACCEPT_AUTH": "badger,Wlid1.1,Bearer",
"REMOTE_PORT": "50216",
"REQUEST_METHOD": "HEAD",
"REQUEST_TIME_FLOAT": 1537284526.406,
"REQUEST_TIME": 1537284526
}
HEAD 方法与 GET 相同,只是服务器不得在响应中返回消息正文。来源:[w3.org][1]
第二个隐藏请求
第二个请求有点难以识别,看起来 Excel 模拟了几个用户代理:
{
"HTTP_ACCEPT": "*\/*",
"HTTP_USER_AGENT": "Mozilla\/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident\/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; ms-office)",
"HTTP_ACCEPT_ENCODING": "gzip, deflate",
"REMOTE_PORT": "50221",
"REQUEST_METHOD": "GET",
"REQUEST_TIME_FLOAT": 1537284527.807,
"REQUEST_TIME": 1537284527
}
问题
如何在 Excel 端防止这种行为?
(当然,我可以通过阻止包含“微软Office“或 REQUEST_METHOD”头“,但我更喜欢一个干净的解决方案)。
补充说明
更新 #1
我刚刚发现这个所以-问题,这有点描述了相同的行为:https://stackoverflow.com/questions/24993813/link-in-excel-cause-duplicate-invocation
更新 #2 随着深入研究,我发现越来越多的所以-threads,像这样,对这个“功能”给出了很好的描述:https://webmasters.stackexchange.com/a/71151
不过,还是有一点区别的。我的第一个请求的 REQUEST METHOD 是 HEAD,而不是上面提到的答案中的 OPTION。无论如何,这仍然不能帮助我解决问题。
更新 #3 当我尝试重现这个问题时,我发现提出的请求不是两个而是三个。
答案1
我不确定,但在测试时,我注意到 Excel 正在“Internet Explorer”中打开链接以检查安全性或存在性。
例如,如果你输入了错误的 URL,Excel 会显示无法打开,表示出现了安全问题,而不是浏览器的问题。
我已经测试过了
=HYPERLINK("https://test.test")
并收到了此消息 错误信息
所以我不认为可以通过 excel “修复” 此类问题
答案2
这种行为(至少是第一个 HEAD 请求)是由所谓的Microsoft Office 协议发现引入 Office 2007请参阅 blogs.msdn.microsoft.com:
HEAD 请求的目的是检查内容是否作为文档存在于 URL 位置,而不仅仅是作为只读会话中流下的临时资源
HEAD 方法与 GET 相同,只是服务器不得在响应中返回消息正文。来源:w3.org
根据此 technet 线程没有办法禁用此功能。
解决方法
由于没有办法真正禁用此功能,您只能在服务器端阻止请求(或使用客户端防火墙...):
PHP 中,可以使用以下几行代码拒绝此类请求。这只会捕获第一个隐藏请求的 REQUEST_METHOD,并再次检查第二个隐藏请求的奇怪用户代理:
if ($_SERVER['REQUEST_METHOD'] == 'HEAD' OR
strpos($_SERVER['USER_AGENT'], 'ms-office') != NULL) {
throw new Exception('This script may only be called directly');
die();
}
小心:这在上述场景中有效,请随意调整它以避免阻塞流量,这实际上是“想要的”。
进一步阅读
- 如何在 Office 2003 中打开网站上的文档(部分:了解 Microsoft Office 协议发现)