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

onl*_*wei 58 javascript iframe httprequest

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

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

<iframe src="someURL"> <!-- is there any place to set headers in this? -->
Run Code Online (Sandbox Code Playgroud)

Fel*_*wMD 53

您可以在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 :(');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

保留响应的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

  • 但是如果我们遇到CORS错误,如何克服呢? (3认同)
  • 这很好用,但我有一个问题。生成的 url 使用 blob 中的顶级域,因此 iframe 尝试通过顶级域(例如 localhost)加载其资源。难道我做错了什么? (2认同)

Nie*_*sol 24

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

  • 嗨Niet,您能否在JSFiddle中提供示例实现代码 (4认同)
  • 这样的预加载脚本中的请求不会被发送到不同的域,从而违反同源策略吗? (2认同)

poi*_*rez 6

由于 @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;
Run Code Online (Sandbox Code Playgroud)

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