【问题标题】:Data URI scheme and Internet Explorer 9 Errors数据 URI 方案和 Internet Explorer 9 错误
【发布时间】:2023-04-06 10:03:02
【问题描述】:

在 IE 版本 6-9 中使用 RFC 2397 数据 URL 方案时遇到问题。下面的示例代码在使用当前版本的 Safari、FF、Opera 和 Chrome 时可以正常工作。

data:text/html;base64,PG1ldGEgaHR0cC1lcXVpdj0icmVmcmVzaCIgY29udGVudD0iMDt1cmw9aHR0cDovL2dvb2dsZS5jb20vIj4g

或

data:text/html,%3Cmeta%20http-equiv%3D%22refresh%22%20content%3D%220%3Burl%3Dhttp%3A//google.com/%22%3E%20

如果将上述代码粘贴到几乎任何浏览器(不包括 IE)中,它将导航到 google.com,当尝试使用 IE 时,它会失败并出现以下错误。

网页无法显示

最可能的原因:

  • 此网页上的某些内容或文件需要您尚未安装的程序。

你可以尝试什么:

在线搜索可用于查看此 Web 内容的程序。

重新输入地址。

检查生成的 IE 错误页面的页面源时,有一个引用文件关联和协议的链接。

协议类型:

描述:未知

Windows 无法识别此协议。

我意识到使用 data: 协议可能不是最直接的,或者在大多数情况下不是最好的选择,但我必须将它用于这个特定的项目。

我已经到处寻找解决方案并尝试了许多使用 IE 的示例,希望这是我的语法,但尚未找到解决方案。

【问题讨论】:

  • 为什么必须在这个项目中使用data: 协议?如果你必须支持的浏览器不支持它,这似乎是一个奇怪的要求。
  • 我大约 4 分钟前才发现 IE 确实支持它。一段时间以来,它一直被认为是受支持的 IE 协议。根据客户的要求,我需要使用它用客户端 javascript 替换服务器端 http 处理程序。数据存档位于 Unix 机器上,新的面向外部的服务器基于 Windows,使用 .NET 4.0 框架。

标签: internet-explorer protocols rfc data-url


【解决方案1】:

数据 URI 不能用于导航、脚本或填充 IE 中的框架或 iframe 元素。

根据http://msdn.microsoft.com/en-us/library/cc848897%28v=vs.85%29.aspx:

数据 URI 仅支持以下元素和/或 属性。

object (images only)
img
input type=image
link
CSS declarations that accept a URL, such as background, backgroundImage, and so on.

数据 URI 可以嵌套。

出于安全原因,数据 URI 仅限于下载 资源。 数据 URI 不能用于导航、脚本或 填充框架或 iframe 元素。

数据 URI 不能超过 32,768 个字符。

资源数据必须正确编码;否则会发生错误 并且资源未加载。 “#”和“%”字符必须是 编码,以及控制字符、非美国 ASCII 字符和 多字节字符。

有关详细信息,请参阅 RFC2397:“数据”URL 方案。

适用于 Windows Internet Explorer 8 或更高版本。**

【讨论】:

    【解决方案2】:

    Internet Explorer 确实支持Data URIs(资源有点过时了)。虽然它有一些安全考虑,但可以防止它允许恶意尝试重定向用户,或者允许黑客在不需要 3rd 方脚本或托管资源的情况下进行网络钓鱼。

    这意味着您可以将它与 JavaScript 一起使用:

    <script src="data:text/javascript;base64;YWxlcnQoIldvcmtzIik7"></script>
    

    级联样式表(带或不带 base64 编码):

    <link rel="stylesheet" href="data:text/css;base64,Ym9keXtjb2xvcjpncmVlbn0=">
    <link rel="stylesheet" href="data:text/css,body%7Bcolor:green%7D">
    

    甚至是图片:

    <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4QBgRXhpZgAASUkqAAg
    AAAACADEBAgAHAAAAJgAAAGmHBAABAAAALgAAAAAAAABQaWNhc2EAAAMAAJAHAAQAAAAwMjIwAqAEAAE
    AAAAbAAAAA6AEAAEAAAAbAAAAAAAAAP/bAIQAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcHBggMCgwMCwo
    LCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFAEDBAQFBAUJBQUJFA0LDRQUFBUUFBQUFBQUDxQ
    QFBUUExUVFBQUEBUUFQ4UFBQUEhISDxURFQ8SFRQSEBAQDQ8P/8AAEQgAGwAbAwERAAIRAQMRAf/EABg
    AAAMBAQAAAAAAAAAAAAAAAAUHCAIG/8QAKxAAAQMDAwMDAwUAAAAAAAAAAQIDBAUGEQASIQciMQgTFEF
    RgRVhcaHD/8QAGQEAAwEBAQAAAAAAAAAAAAAABAUGBwMC/8QALxEAAQMCAgcHBQEAAAAAAAAAAQACAwQ
    RBSESMUFRYZHBEyJxobHR4RVDgfDxFP/aAAwDAQACEQMRAD8AGdeKdd3Um670bjz0waNQpzVKpVOWtSE
    uqSgKefIztKipQwSOU4wRjuBq6tj52h2YTbA8Nkp6UmMaLzzS1sz0ru1qqNyrkrqWIiMrfjsjctw4HGT
    wM/ngaEmxJjBaNqdRYPJpaczr8FTXRY1h7p9dVg1GpSZzNBkobYcec3qfgup9xjefqUqQ4n+ED651RYf
    Utla2UjMKBx6hdTvdEw2ac7JR13psz+rytkUqTv8AITq1bVZDNZo6ncCQFYFH9O1vS+lVrOW1bD0REtl
    uW8hi45Ty0hSAUkOrKlLyNvA27eBnCdZbUxNv3GjkFudDWvved55k9QpI9S0y7ujfqUk2jZ4bcaetuFP
    MSSFyENrW84h1zevcvOEgZzj9hnQ76aAQh0+Wezw1JjR1dVPO5kJuNxJ360Stj1LU/ooqREuuA9Krs4s
    LqM2A0lbDSACG0kDlRTlZKUjHJx5xplhjWui7mq+Xkk2PhxqgDrDRfxuUmL89awuO8KrUU202lDz3Z7K
    vbSpIASlW3ZwSACR9ydUsc/ZtDBs4qLkw4TPMjjmeCGSurEun2rRqJBvStJq5U6iSiLUZHx0BKRtQ2pT
    hJwPBASnggDxqUjDzdxBtx+PlaTpQEhha38DqegCM2PdL6apMrkyHKn1FuIiOuoyCpbiEA57nFLVkcnC
    OAST4OgqqMygMLsr6lQUZigvIxlstdv3pdbqsGy7nn1ym3pcEy3am06hwvsKZMYtrYQUZK1pVu2r5SkK
    APPGjIJXQQt7Jml/VJ4lCKmre50lj8JYVDopYQmu/GviZJYz2OtQS6lQ+4UlZB/B16+oz7YDzCB/wsH3
    fJIx+W8qRKWXFbxIUQrPPCiB/QGmLNQQriS4lODo1Mk1/qBQaJUJcmVSXJrYXEW+v21dw8gHnQNaBHA6
    Ros62tOaKV8kjY3OJbuWrXkya/wBV6z8ubMCn1y1OLjSnI61YXwNzaknaMDtzjgccDXKoPZUzdEDZsB9
    UFGTJO7SO/wBV0kq3mRIcHzaue4+axLP+uk/bO3DkPZMxE3jzPuv/2Q==">
    

    但是,您不能将它们与window.open 或iframe 一起使用,因为它们会导致一些非常危险的事情,包括Phishing with Data URIs:

    <iframe src="data:text/html;base64,PGJ1dHRvbiBpZD0iX3BheXBhbCI+TG9nIGludG8gUGF5cG
    FsPC9idXR0b24+DQo8c2NyaXB0Pg0KICAgIF9wYXlwYWwuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCB
    mdW5jdGlvbiAoKSB7DQogICAgICAgIGFsZXJ0KCJUaGlzIGNvdWxkIGhhdmUgYmVlbiB1Z2x5IGZvciB5
    b3UuLi4iKTsNCiAgICB9LCBmYWxzZSk7DQo8L3NjcmlwdD4="></iframe>
    

    最后一个示例很可能是 PayPal 登录屏幕的完整复制品。相反,它只是一个绑定了事件处理程序并监听点击的 HTML 按钮。 window.open:

    window.open("data:text/html;base64,PHN0cm9uZz5XQVQhPzwvc3Ryb25nPg==", "OHAI");
    

    因此 Internet Explorer 10 支持此功能,但它可以保护最终用户免受恶意使用它的人的侵害。我敢肯定,如果微软确定了一种更好的方法来保护他们的用户群,他们会很乐意解除这一限制。

    在情况发生变化之前,您需要找到另一种方法来包含您的 FLV 文件。在旁注中,您可能不想在 Stack Overflow 上从您的应用程序中分享这样的实际数据。

    【讨论】:

    • 嗯...我不相信 iframe 数据网络钓鱼比仅在您的页面上显示与 paypal 登录屏幕相同的 html 更危险。与使用“window.open”访问数据 URL 相同 - 为什么不只包含指向具有适当外观的 HTML 以进行网络钓鱼攻击的页面的链接?
    【解决方案3】:

    这里解释了两种替代解决方案:http://sparecycles.wordpress.com/2012/03/08/inject-content-into-a-new-iframe/

    我能看出的主要区别是 iframe 与原始页面具有相同的来源,这可能不是我们所希望的(我不确定安全隐患,例如,对于加载的资源,引用者或 cookie 可能是什么)。

    这里有一个使用 javascript: 方案技术的示例:http://jsbin.com/uhenuz/4(如果与 https 一起使用,则需要额外的谷歌搜索和良好的测试来检查混合的 https/http 警告永远不会出现。)

    【讨论】:

      【解决方案4】:

      对我来说,找到document.execCommand 是救命稻草。它像其他一些示例一样使用iFrame,但execCommand 使Save As 功能保持一致。

      这是一个例子

      var getCsvFileForIE = function(target) {
        var csvData = target.attributes["data-csv"].value;
        if (navigator.appName === "Microsoft Internet Explorer") {
          csvData = decodeURIComponent(csvData);
      
          var iframe = document.getElementById('csvDownloadFrame');
          iframe = iframe.contentWindow || iframe.contentDocument;
      
          csvData = 'sep=,\r\n' + csvData;
      
          iframe.document.open("text/html", "replace");
          iframe.document.write(csvData);
          iframe.document.close();
          iframe.focus();
          iframe.document.execCommand('SaveAs', true, 'data.csv');
        } else {
          if (console && console.log) {
            console.log('Trying to call getCsvFileForIE with non IE browser.');
          }
        }
      };
      

      我们为 IE 和所有其他浏览器执行此操作,我们使用标准数据 URI 链接。您可以查看full gist 了解更多详情。向Andrew Blondeau for the direction 致敬。


      更新

      确定浏览器是否支持数据 URI 的更好方法

      supportsDataUri = 'download' in document.createElement('a');

      IE 似乎仍然遇到问题。对于 IE10+,您可能需要使用 msSaveOrOpenBlob,对于 IE8/9,您仍然需要在 iFrame 中使用 execCommand。

      更新 2

      有一个Modernizr issue 用于检测数据 uri 方案。它引用another SO answer。请务必检查这些内容。

      【讨论】:

      • 您关于检查锚元素上 download 属性是否存在的建议是我发现的用于确定浏览器对超链接中数据 URI 的支持的最轻量级方法,尽管我最终使用了稍微不同的方法语法:supportsDataUri = typeof document.createElement("a").download !== "undefined";
      • 尝试在新窗口中打开数据 URI 时,在 Edge 浏览器中检查下载属性不起作用。但是,Modernizr 问题中提到的测试确实如此。
      【解决方案5】:

      根据佛朗哥在这里的回答:CSV file export For IE

      只需用它创建一个 Blob 对象

      //Save file
      if (isMicrosoftIE()) {
          csvData = decodeURIComponent(csv);
      
          if(window.navigator.msSaveBlob){
              var blob = new Blob([csvData],{ type: "application/csv;charset=utf-8;"});
              navigator.msSaveBlob(blob, filename);
          }
      }
      else
      {
          csvData = "data:application/csv;charset=utf-8," + encodeURIComponent(csv);
          $(this).attr({
              "href": csvData,
              "target": "_blank",
              "download": filename
          });
      }
      

      它对我有用!

      【讨论】:

        【解决方案6】:

        我在寻找一种方法来检测文件的数据 uri 支持(在我的例子中是 PDF)时,我来到了这里。 Modernizr 检查图像支持的方法不够好,因为 Internet Explorer 11 和 Edge 25 确实支持,但不支持 application/pdf 等文件类型。 Snekse 检查下载属性的方法适用于 IE,但不适用于 Edge。最终,我编写了自己的特征检测脚本,使用 AJAX 调用尝试打开数据 URI 并检查错误。这是我使用的脚本(在 IE 11、Edge 25、Firefox 46 和 Chrome 49 中测试):

        checkDataURISupport(function (checkResult) {
            if (checkResult) {
                alert('Files in data URIs are supported.');
            } else {
                alert('Files in data URIs are NOT supported.');
            }
        })
        
        function checkDataURISupport(callback) {
            try {
                var request = new XMLHttpRequest();
                request.onload = function reqListener() {
                    callback(true);
                };
                request.onerror = function reqListener() {
                    callback(false);
                };
                request.open('GET', 'data:application/pdf;base64,cw==');
                request.send();
            } catch (ex) {
                callback(false);
            }
        }
        

        更新

        我意识到任何测试数据 URI 是否支持 iframe 的代码也在测试是否支持在新窗口中打开数据 URI。因此,this SO answer 中提到并链接到 Snekse 的答案更新中的解决方案在技术上是优越的,我建议使用它而不是上面的代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-10
          • 2012-07-29
          • 2012-08-27
          • 1970-01-01
          • 1970-01-01
          • 2013-03-16
          相关资源
          最近更新 更多