JavaScriptでAJAX呼び出しを行うときに、HTTPリクエストヘッダーを非常に簡単に設定できることを理解しています。
ただし、スクリプトを介してiframeをページに挿入するときにカスタムHTTPリクエストヘッダーを設定することもできますか?
<iframe src="someURL"> <!-- is there any place to set headers in this? -->
回答:
いいえ、できません。ただし、iframe
ソースをある種のプリロードスクリプトに設定することもできます。このスクリプトは、AJAXを使用して、必要なすべてのヘッダーを含む実際のページをフェッチします。
必要なヘッダーを設定して、JavaScriptでリクエストを行うことができます。次に、iframeにURL.createObjectURL()
適したものを取得できます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
URL.createObjectURL()はChrome 71では非推奨であることが判明しました(https://developers.google.com/web/updates/2018/10/chrome-71-deps-remsを
参照)
@Niet the darkAbsolと@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の回答が最新のブラウザーで機能しないため、同じアプローチを使用しましたが、iframesrcDoc属性を使用しました。
以下の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を渡すことは非推奨ではなく、実際、かなり広く、使用量が増えています。私は物事を最新に保つ努力に感謝します:)