是否可以将请求标头添加到 iframe src 请求?

IT技术 javascript iframe httprequest
2021-03-21 18:33:17

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

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

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

您可以在 javascript 中发出请求,设置您想要的任何标头。然后你就可以URL.createObjectURL(),得到一些适合srciframe 的东西

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

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

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

我相信 Niet 的意思是这样的 stackoverflow.com/a/17695034/1524918
2021-04-22 18:33:17
默认发送哪些标头?这有什么标准吗?
2021-05-07 18:33:17
嗨 Niet,您能否提供 JSFiddle 中的示例实现代码
2021-05-16 18:33:17
这样的预加载脚本中的请求不会被发送到不同的域,从而违反同源策略吗?
2021-05-17 18:33:17

由于@FellowMD 的回答由于 createObjectURL 的贬值而不适用于现代浏览器,因此我使用了相同的方法,但使用了 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

此解决方案未展示如何将请求中的标头设置为 fetchContent
2021-04-20 18:33:17
createObjectURL仅弃用 MediaStream 参数。不反对传递 Blob,事实上,它的使用范围非常广泛且不断增加不过,我很欣赏保持最新状态的努力:)
2021-05-06 18:33:17
@poiuytrez 当我想获取带有自定义标题的内容时,我收到了这个问题中所问的错误你能看一下吗
2021-05-20 18:33:17

事实证明 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

您可以将该方法用于 Blob 对象。在你的情况下,就像URL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
2021-04-29 18:33:17
来自 Google 链接:“URL.createObjectURL() 方法已从 MediaStream 界面中删除。” 影响 MediaStream 接口的弃用是否与其他答案相关?(我认为不会。)
2021-04-30 18:33:17
createObjectURL仅弃用 MediaStream 参数。不反对传递 Blob,事实上,它的使用范围非常广泛且不断增加不过,我很欣赏保持最新状态的努力:)
2021-05-01 18:33:17
@TheMaster 这确实是文档所说的,但我花了几个小时试图让它工作并且没有成功。它无法推测原因。上面显示的代码是我编码时最终工作的代码,我没有带宽再试一次。
2021-05-08 18:33:17
不弃用。仅从 MediaStream 中删除
2021-05-17 18:33:17