在 Chrome 中将 iframe 与本地文件一起使用
Posted
技术标签:
【中文标题】在 Chrome 中将 iframe 与本地文件一起使用【英文标题】:Using iframe with local files in Chrome 【发布时间】:2013-07-30 19:27:38 【问题描述】:我很难弄清楚如何从外部页面访问加载到 iframe 中的页面。两个页面都是本地文件,我用的是 Chrome。
我有一个外页和许多内页。外部页面应该始终显示内部页面的页面标题(这在我的应用程序中是有意义的,在这个精简的示例中可能不那么有意义)。这在 AppJS 中没有任何问题,但我被要求让这个应用程序直接在浏览器中工作。我收到错误“Blocked a frame with origin "null" from access a frame with origin "null"。协议、域和端口必须匹配。”。
我认为这是由于 Chrome 对本地文件的同源政策,但这并没有帮助我直接解决问题。我可以通过使用每个Ways to circumvent the same-origin policy 的window.postMessage 方法来解决这个精简示例中的问题。但是,除了这个示例之外,我还想从外部页面操作内部页面的 DOM,因为这将使我的代码更加简洁 - 所以发布消息并不能完全完成这项工作。
外页
<!DOCTYPE html>
<html>
<head>
<meta name="viewport">
</head>
<body>
This text is in the outer page
<iframe src="html/Home.html" seamless id="PageContent_Iframe"></iframe>
<script src="./js/LoadNewPage.js"></script>
</body>
</html>
内页
<!DOCTYPE html>
<html>
<head>
<title id="Page_Title">Home</title>
<meta name="viewport">
</head>
<body>
This text is in the inner page
</body>
</html>
var iFrameWindow = document.getElementById("PageContent_Iframe").contentWindow;
var pageTitleElement = iFrameWindow.$("#Page_Title");
根据Is it likely that future releases of Chrome support contentWindow/contentDocument when iFrame loads a local html file from local html file?,我尝试使用标志启动 Chrome
--allow-file-access-from-files
但结果没有变化。
根据Disable same origin policy in Chrome,我尝试使用标志启动 Chrome
--disable-web-security
但结果还是没有变化。
根据What does document.domain = document.domain do?,我让两个页面都运行命令
document.domain = document.domain;
这导致了错误“阻止了来源为“null”的框架访问来源为“null”的框架。请求访问的框架将“document.domain”设置为“”,但被访问的框架确实不是。两者都必须将“document.domain”设置为相同的值才能允许访问。"
为了好玩,我让两个页面都运行命令
document.domain = "foo.com";
这导致了错误“Uncaught Error: SecurityError: DOM Exception 18”。
我在挣扎。任何知识渊博的人的帮助都会很棒!谢谢!
【问题讨论】:
【参考方案1】:很抱歉,我已经尝试了数周来解决这个问题(我的项目需要它),但我的结论是这是不可能的。
通过javascript和chrome进行本地访问有很多问题,其中一些可以使用--allow-file-access-from-files
和--disable-web-security
解决,包括一些HTML5离线功能,但我绝对认为没有办法访问本地文件.
我建议您不要浪费时间试图绕过这一点,并尝试发布您可以解释到内页的消息,这样您就可以在那里进行 DOM 修改。
【讨论】:
男孩,这太糟糕了。非常感谢您的回复!【参考方案2】:根据我们在一分钟前在我的立方体中的讨论:)
我在尝试使 AJAX 发布请求正常工作时遇到了同样的问题 (Ajax post response from express js keeps throwing error)。
让我感到困惑的不是直接从文件系统运行文件,而是从本地服务器运行它。我使用 node 来运行 express.js。您可以使用以下命令安装 express:npm install -g express
完成后,您可以使用以下命令创建一个 express 项目:express -s -e expressTestApp
现在,在该文件夹中,您应该会看到一个名为 app.js 的文件和一个名为 public 的文件夹。将您希望使用的 html 文件放在公用文件夹中。我将文件 app.js 替换为以下代码:
var express = require('/usr/lib/node_modules/express');
var app = express();
app.use(function(err, req, res, next)
console.error(err.stack);
res.send(500, 'Something broke!');
);
app.use(express.bodyParser());
app.use(express.static('public'));
app.listen(5555, function() console.log("Server is up and running"); );
注意,require 行可能不同。您必须找到您的系统实际放置快递的位置。您可以使用以下命令执行此操作:sudo find / -name express
现在,使用以下命令启动 express Web 服务器:node app.js
此时,网络服务器已启动并正在运行。继续打开浏览器并导航到您的 IP 地址(或者如果您与服务器在同一台机器上,则为 127.0.0.1)。使用 ip 地址:portnumber\filename.html 其中端口号是我们创建的 app.js 文件中的 5555。
现在在那个浏览器中,您不应该(并且在我们测试它时没有)再遇到任何这些相同的问题。
【讨论】:
请注意,如果您安装了 Python,则可以应用您在此处建议的相同方法和set up a Web server one line:python -m SimpleHTTPServer [port]
哇,真是太好了。没有看到那个。我在相同的源代码上对其进行了测试,它可以工作,但比 express 慢。以如此之快的速度启动和运行是非常了不起的,当然也需要考虑权衡。
对于 Python 3,请改用:python -m http.server [port]
另一种选择是 Node 包 serve。全局安装后,您只需使用终端导航到该 html 目录并运行命令 serve
(默认为端口 3000)或 serve -p [port]
。【参考方案3】:
file:// 协议和 http:// 协议在 iframe 方面表现得非常不同。我遇到了您在 PhoneGap 上使用文件协议访问本地 assets/www 文件夹中的所有本地文件的应用程序所描述的相同问题。
如果出于安全原因,现代浏览器似乎阻止使用 iframe 中的文件协议显示“本地”文件。
我们最终放弃了 iframe,只使用 div 作为“视口”。幸运的是,我们的应用程序的整体大小并没有那么大,所以我们设法将所有内容加载到一个页面中。
【讨论】:
我有点好奇这些安全原因是什么。老实说,我看不出有任何理由禁止这样做。如果有特定情况,如果 Chrome 可以提供合理的消息,那就太好了,因为我确实希望协议、域和端口对于一堆本地文件是相同的。 @JacekPrucia 我会破解:原因是如果有人给你一个访问本地文件的应用程序,那么如果 Chrome 没有阻止它,它可以继续读/写你的本地文件。 (如果您正在开发自己的应用程序并且只想访问自己的文件系统,这并不明显,但如果您将应用程序分发给其他人,则变得更加明显。) @martinjakubik 当然可以,但我仍然认为这没有什么害处。假设您的页面植根于“C:\Projects\Test\Test.html”。恶意页面只能在该特定文件夹中写入本地文件(应用于文件夹时的同源策略)。当然它可以创建恶意文件 - 伪装成无辜屏幕保护程序的应用程序,但是您仍然需要用户操作才能造成损害。如果您只是使用该应用程序,我仍然看不到它会以何种方式损坏本地系统。 @JacekPrucia 我不知道...我认为它仍然可以退出文件夹并覆盖(或读取)其他文件。 @martinjakubik 好吧......从技术上讲,它可以做到这一点。但是,由于它们确实将 http 协议访问限制为“同源策略”,因此它们也可以以几乎相同的方式限制文件协议。出于某种原因,他们没有费心想出一个场景,只是禁用了整个东西,迫使我使用本地网络服务器......以上是关于在 Chrome 中将 iframe 与本地文件一起使用的主要内容,如果未能解决你的问题,请参考以下文章
使用 JQuery 访问由 chrome 扩展注入的 iframe
使用文件协议在 Chrome 中调用 iframe 中定义的 JavaScript 函数