我了解您可以在JavaScript中进行AJAX调用时非常轻松地设置HTTP请求标头。
但是,通过脚本将iframe插入页面时,是否还可以设置自定义HTTP请求标头?
<iframe src="someURL"> <!-- is there any place to set headers in this? -->
Answers:
不,你不能。但是,您可以将iframe
源设置为某种预加载脚本,该脚本使用AJAX来获取包含所有所需标题的实际页面。
您可以使用javascript发出请求,设置所需的任何标题。然后,您可以URL.createObjectURL()
获取适合src
iframe的内容。
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
事实证明,在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
URL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
createObjectURL
仅不推荐使用MediaStream参数。通过Blob并不被弃用,实际上它的使用范围越来越广,使用率也越来越高。我感谢为使事情保持最新而付出的努力:)
由于createObjectURL的贬值,@ FellowMD答案在现代浏览器上不起作用,因此我使用了相同的方法,但使用了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并不被弃用,实际上它的使用范围越来越广,使用率也越来越高。我感谢为使事情保持最新而付出的努力:)