代码之家  ›  专栏  ›  技术社区  ›  Dan Fabulich

在ie xmlhttprequest中读取file://urls

  •  12
  • Dan Fabulich  · 技术社区  · 15 年前

    我正在开发一个JavaScript应用程序,它可以从Web服务器(通过HTTP)运行,也可以从文件系统(在file://url上)运行。

    作为这段代码的一部分,我需要使用xmlhttpRequest在页面所在的目录和子目录中加载文件。

    此代码在Web服务器上执行时工作正常(“通过”),但在Internet Explorer 8中运行文件系统时不工作(“失败”):

    <html><head>
    <script>
    window.onload = function() {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", window.location.href, false);
      xhr.send(null);
      if (/TestString/.test(xhr.responseText)) {
        document.body.innerHTML="<p>PASS</p>";
      }
    }
    </script>
    <body><p>FAIL</p></body>
    

    当然,它一开始会失败,因为在文件系统上根本无法运行任何脚本;系统会提示用户一个黄色条,警告“为了帮助保护您的安全,Internet Explorer已限制此网页运行可以访问您的计算机的脚本或ActiveX控件。”

    但是,即使我单击了这个栏并“允许被阻止的内容”,页面仍然失败;我在xhr.open调用中得到一个“拒绝访问”错误。

    这让我困惑,因为 MSDN 表示“出于开发目的,允许从本地计算机区域使用文件:/协议。”此本地文件应该是本地计算机区域的一部分,对吗?

    我怎样才能让这样的代码工作?我可以向用户提示安全警告;我不能强制他们关闭控制面板中的安全。

    编辑: 事实上,在我的示例中,我没有加载XML文档;我正在加载纯文本文件(.txt)。

    4 回复  |  直到 6 年前
        1
  •  8
  •   Don    15 年前

    嗯,这是本地xmlhttpRequest对象和ActiveX对象之间的区别吗?我好像记得一些关于这个的事情。也就是说,而不是

    var xhr = new XMLHttpRequest();
    

    尝试

    var xhr = new ActiveXObject("MSXML2.XMLHTTP");
    

    显然,要进行一些检查,看看浏览器是否支持ActiveX。当然,这也仅限于IE。

        2
  •  7
  •   Jan Zich    14 年前

    我只是碰巧遇到了完全相同的问题。如上所述,非本机ActiveX“构造函数”可以工作。我不确定这两个对象是否应用了不同的策略,但由于jquery也提到了相同的问题,所以这可能是一个真正的bug。以下是jquery源代码的相关代码(1.4.2,第4948行):

    // Create the request object; Microsoft failed to properly
    // implement the XMLHttpRequest in IE7 (can't request local files),
    // so we use the ActiveXObject when it is available
    // This function can be overriden by calling jQuery.ajaxSetup
    xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
        function() {
            return new window.XMLHttpRequest();
        } :
        function() {
            try {
                return new window.ActiveXObject("Microsoft.XMLHTTP");
            } catch(e) {}
        }
    
        3
  •  7
  •   Adriano Carneiro Tigran    13 年前

    我怎样才能让这样的代码工作?

    如上所述,这看起来像是 Microsoft XMLHttpRequest . jquery(2011年7月)还写道:

    Microsoft未能在IE7中正确实现XMLHttpRequest(无法请求本地文件)

    我也为IE8确认了这个失败。

    解决方案是使用 new window.ActiveXObject( "Microsoft.XMLHTTP" ) 对于本地文件,如果 XMLHttpRequest 不起作用。

    失败在于 xhr.open 这样它就可以在那里被捕获,然后尝试 ActiveXObject 如下:

    var xhr = new XMLHttpRequest()
    try {
        xhr.open('GET', url, true)
    }
    catch(e) {
        try {
            xhr = new ActiveXObject('Microsoft.XMLHTTP')
            xhr.open('GET', url, true)
        }
        catch (e1) {
            throw new Error("Exception during GET request: " + e1)
        }
    }
    

    此代码至少将使用标准 对象 对于IE9(未测试)和未来的IE浏览器,如果/当Microsoft修复了故障。与 jQuery 以上代码,非标准 Microsoft.XMLHTTP 将在任何时候使用 ActiveX对象 是可用的,即使Microsoft修复了故障。

        4
  •  1
  •   Justin Greywolf    6 年前

    我知道这很古老,但我想用更多的细节来说明正在发生的事情,并提供一些潜在的选择。

    首先,事实上 IE中的一个缺陷,但Chrome中也存在一个安全特性。

    基本上,任何带有file://prefix的资源URI都不允许使用xmlhttprequest加载带有file://prefix的任何其他资源URI。

    在IE中,您将看到一条拒绝访问的消息。在chrome中,您将看到“加载资源失败:访问控制不允许源站为空” 更多信息-gt; Information on IE Information on Chrome (查找--允许从文件访问文件)

    IE的一个有趣之处在于,如果您使用.NET浏览器 控制WinForm或Silverlight应用程序内部,此功能是 禁用,您将不会有相同的问题。

    我知道有两种解决方法-没有一种是理想的,因为它们会禁用安全保护措施。

    • IE:第一个也是最“良性”的是,您可以将调用页的URI添加到受信任的站点区域(取消选中“启用保护模式”)。
    • IE:在上面的链接后面有一个注册表设置,您可以修改它来禁用这个功能-但是这必须在每台试图加载资源的机器上完成。
    • chrome:上面的链接是指在启动chrome时使用命令行开关来禁用该功能。

    再一次,这是一个 安全功能 在浏览器中减轻潜在威胁向量-类似于跨域脚本块。