【问题标题】:Is it possible to add Request Headers to an iframe src request?是否可以将请求标头添加到 iframe src 请求?
【发布时间】:2012-11-06 03:16:35
【问题描述】:

我了解到,在 JavaScript 中进行 AJAX 调用时,您可以非常轻松地设置 HTTP 请求标头。

但是,在通过脚本将 iframe 插入页面时,是否也可以设置自定义 HTTP 请求标头?

<iframe src="someURL"> <!-- is there any place to set headers in this? -->

【问题讨论】:

    标签: javascript iframe httprequest


    【解决方案1】:

    您可以在 javascript 中发出请求,设置您喜欢的任何标头。然后你可以URL.createObjectURL(),得到适合iframe的src的东西。

    var xhr = new XMLHttpRequest();
    
    xhr.open('GET', 'page.html');
    xhr.onreadystatechange = handler;
    xhr.responseType = 'blob';
    xhr.setRequestHeader('Authorization', 'Bearer ' + token);
    xhr.send();
    
    function handler() {
      if (this.readyState === this.DONE) {
        if (this.status === 200) {
          // this.response is a Blob, because we set responseType above
          var data_url = URL.createObjectURL(this.response);
          document.querySelector('#output-frame-id').src = data_url;
        } else {
          console.error('no pdf :(');
        }
      }
    }
    

    保留响应的 MIME 类型。因此,如果您收到 html 响应,则 html 将显示在 iframe 中。如果您请求 pdf,浏览器 pdf 查看器将启动 iframe。

    如果这是长期存在的客户端应用程序的一部分,您可能需要使用URL.revokeObjectURL() 以避免内存泄漏。

    对象 URL 也很有趣。它们的形式为blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170。实际上,您可以在新选项卡中打开它们并查看响应,当创建它们的上下文关闭时它们会被丢弃。

    这是一个完整的例子:https://github.com/courajs/pdf-poc

    【讨论】:

    • 完美。完美地工作。谢谢。
    • 你这个人!我正在开发一个受此代码启发的 Angular 5 组件,以在 Angularjs 中显示 pdf 预览。这对我帮助很大
    • @BSSchwarzkopf 看起来你是对的。 Edge 支持 Blob URL,但它们在 iframe 的 src 属性中不起作用。我认为它违反了规范:“这个方案应该能够与 Web API 一起使用......以及设计用于 HTTP URL 的元素......一般来说,这个方案应该被设计为可以在 Web 上使用 URL 的任何地方使用。”边缘跟踪器问题:developer.microsoft.com/en-us/microsoft-edge/platform/issues/… 规范:w3.org/TR/FileAPI/#use-cases-scheme
    • 我得到“无法在 'URL' 上执行 'createObjectURL':找不到与提供的签名匹配的函数。”在 Chrome 84.0.4147.105 上。
    • @poiuytrez 这意味着您传递了错误的参数。它需要文件、Blob 或 MediaSource。也许你传递的是 null、undefined、promise 或 Request 对象?
    【解决方案2】:

    不,你不能。但是,您可以将 iframe 源设置为某种预加载脚本,该脚本使用 AJAX 来获取包含您想要的所有标题的实际页面。

    【讨论】:

    • Hi Niet,能否提供 JSFiddle 中的示例实现代码
    • 我相信 Niet 的意思是这样的 stackoverflow.com/a/17695034/1524918
    • 这样的预加载脚本中的请求会不会被发送到不同的域,从而违反同源策略?
    • 默认发送哪些标头?这有什么标准吗?
    【解决方案3】:

    由于 createObjectURL 的贬值,@FellowMD 的答案不适用于现代浏览器,因此我使用了相同的方法,但使用了 iframe srcDoc 属性。

    1. 使用 XMLHttpRequest 或任何其他方法检索要在 iframe 中显示的内容
    2. 设置iframe的srcdoc参数

    请在下面找到一个 React 示例(我知道这是矫枉过正):

    import React, {useEffect, useState} from 'react';
    
    function App() {
      const [content, setContent] = useState('');
    
    
      useEffect(() => {
        // Fetch the content using the method of your choice
        const fetchedContent = '<h1>Some HTML</h1>';
        setContent(fetchedContent);
      }, []);
    
    
      return (
        <div className="App">
          <iframe sandbox id="inlineFrameExample"
                  title="Inline Frame Example"
                  width="300"
                  height="200"
                  srcDoc={content}>
          </iframe>
    
    
        </div>
      );
    }
    
    export default App;
    

    现在大多数浏览器都支持 Srcdoc。看来Edge实现有点晚了:https://caniuse.com/#feat=iframe-srcdoc

    【讨论】:

    • createObjectURL 仅在 MediaStream 参数中被弃用。不推荐传递 Blob,实际上是 sees pretty wide and increasing usage。不过,我很感激为保持最新状态所做的努力:)
    • @poiuytrez 当我想获取带有自定义标头的内容时,我收到this question 中询问的错误,请您看一下
    • 这个解决方案没有展示如何在请求中设置headers来获取内容
    【解决方案4】:

    事实证明 URL.createObjectURL() 在 Chrome 71 中已被弃用
    (见https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems
    在 @Niet the dark Absol 和 @FellowMD 的出色答案的基础上,如果您需要传入身份验证标头,这里是如何将文件加载到 iframe 中。 (您不能只将 src 属性设置为 URL):

    $scope.load() {
        var iframe = #angular.element("#reportViewer");
        var url = "http://your.url.com/path/etc";
        var token = "your-long-auth-token";
        var headers = [['Authorization', 'Bearer ' + token]];
        $scope.populateIframe(iframe, url, headers);
    }
    
    $scope.populateIframe = function (iframe, url, headers) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.onreadystatechange = handler;
        xhr.responseType = 'document';
        headers.forEach(function (header) {
            xhr.setRequestHeader(header[0], header[1]);
        });
        xhr.send();
    
        function handler() {
            if (this.readyState === this.DONE) {
                if (this.status === 200) {
                    var content = iframe[0].contentWindow ||
                        iframe[0].contentDocument.document || 
                        iframe[0].contentDocument;
                    content.document.open();
                    content.document.write(this.response.documentElement.innerHTML);
                    content.document.close();
                } else {
                    iframe.attr('srcdoc', '<html><head></head><body>Error loading page.</body></html>');
                }
            }
        }
    }
    

    向 courajs 大喊:https://github.com/courajs/pdf-poc/blob/master/script.js

    【讨论】:

    • 来自 Google 链接:“URL.createObjectURL() 方法已从 MediaStream 接口中删除。”这种影响 MediaStream 接口的弃用是否与其他答案相关? (我认为不会。)
    • 不推荐使用。仅从 MediaStream 中删除
    • @TheMaster 这确实是文档所说的,但我花了几个小时试图让它工作但没有成功。它无法推测原因。上面显示的代码是我编写代码时最终运行的代码,我没有足够的带宽再试一次。
    • 您可以将该方法用于 Blob 对象。在你的情况下,就像URL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
    • createObjectURL 仅在 MediaStream 参数中被弃用。不推荐传递 Blob,实际上是 sees pretty wide and increasing usage。不过,我很感激为保持最新状态所做的努力:)
    猜你喜欢
    • 2018-09-05
    • 2020-02-21
    • 2012-12-01
    • 2011-10-14
    • 2016-12-22
    • 2012-06-09
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多