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


83

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

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

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

Answers:


31

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


4
嗨,尼耶(Niet),您能在JSFiddle中提供示例实现代码吗
Naveen Reddy

我相信尼特的意思是这样的stackoverflow.com/a/17695034/1524918
瑞安·卡拉

5
这样的预加载脚本中的请求是否会发送到其他域,从而违反“相同来源策略”?
mart1n 2015年

默认发送哪些标题?有什么标准吗?
基金莫妮卡的诉讼

74

您可以使用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


完善。完美地工作。谢谢。
mike123 '17

你这个人!我正在研究受此代码启发的Angular 5组件,以在Angularjs中显示pdf预览。这对我有很大的帮助
FireDragon

谢谢!你救了我的命!
雷纳托·苏扎·德·奥利维拉

1
@BSSchwarzkopf看起来您是对的。Edge支持Edge Blob URL,但它们不能在iframe的src属性中使用。我认为这违反了规范:“该方案应能够与Web API一起使用...以及与旨在用于HTTP URL的元素一起使用...通常,该方案应被设计为只要可以在网上使用URL,就可以使用。” Edge跟踪器上的问题:developer.microsoft.com/zh-cn/microsoft-edge/platform/issues/…规格:w3.org/TR/FileAPI/#use-cases-scheme
FellowMD

我收到“无法在'URL'上执行'createObjectURL':找不到与提供的签名匹配的函数。” 在Chrome 84.0.4147.105上。
poiuytrez

3

事实证明,在Chrome 71中不建议使用URL.createObjectURL()
(请参阅https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems
在@Niet上构建黑暗的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


1
从Google链接:“ URL.createObjectURL()方法已从MediaStream接口中删除。” 是否会影响MediaStream接口的弃用是否与其他答案相关?(我认为不会。)
贾里德·瑟斯克

不推荐使用。只从MediaStream中移除
TheMaster

1
@TheMaster确实是文档中所说的,但是我花了几个小时试图使其工作,但没有成功。它无法推测原因。上面显示的代码是我编写代码时最终可以使用的代码,我没有足够的带宽来再次尝试。
TomEberhard

您可以对Blob对象使用该方法。对于您而言,这就像URL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
u.unver34年

createObjectURL仅不推荐使用MediaStream参数。通过Blob并不被弃用,实际上它的使用范围越来越广,使用率也越来越高。我感谢为使事情保持最新而付出的努力:)
FellowMD '20年

2

由于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并不被弃用,实际上它的使用范围越来越广,使用率也越来越高。我感谢为使事情保持最新而付出的努力:)
FellowMD '20
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.