Rozumiem, że podczas wykonywania wywołań AJAX w JavaScript można bardzo łatwo ustawić nagłówki żądań HTTP.
Czy można jednak ustawić niestandardowe nagłówki żądań HTTP podczas wstawiania elementu iframe do strony za pomocą skryptu?
<iframe src="someURL"> <!-- is there any place to set headers in this? -->
javascript
iframe
httprequest
onlywei
źródło
źródło
Możesz wysłać żądanie w javascript, ustawiając dowolne nagłówki. Wtedy możesz
URL.createObjectURL()
zdobyć coś odpowiedniego dlasrc
elementu 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 :('); } } }
Zachowywany jest typ MIME odpowiedzi. Więc jeśli otrzymasz odpowiedź HTML, kod HTML zostanie wyświetlony w ramce iframe. Jeśli poprosiłeś o plik PDF, przeglądarka PDF w przeglądarce włączy się do elementu iframe.
Jeśli jest to część długotrwałej aplikacji po stronie klienta, możesz chcieć użyć,
URL.revokeObjectURL()
aby uniknąć wycieków pamięci.Adresy URL obiektów są również całkiem interesujące. Są w formie
blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170
. W rzeczywistości możesz je otworzyć w nowej karcie i zobaczyć odpowiedź, a zostaną one odrzucone, gdy kontekst, który je utworzył, zostanie zamknięty.Oto pełny przykład: https://github.com/courajs/pdf-poc
źródło
Okazuje się, że URL.createObjectURL () jest przestarzały w Chrome 71
(patrz https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems )
Opierając się na @Niet the dark Absol i Doskonałe odpowiedzi @ FellowMD, oto jak załadować plik do iframe, jeśli musisz przekazać nagłówki uwierzytelniania. (Nie możesz po prostu ustawić atrybutu src na adres 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>'); } } } }
i krzycz do courajs: https://github.com/courajs/pdf-poc/blob/master/script.js
źródło
URL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
createObjectURL
jest przestarzały tylko dla argumentów MediaStream. Przekazywanie obiektu Blob nie jest przestarzałe i w rzeczywistości powoduje dość szerokie i rosnące użycie . Doceniam jednak wysiłek, aby wszystko było na bieżąco :)Ponieważ odpowiedź @FellowMD nie działa na nowoczesnych przeglądarkach ze względu na deprecjację createObjectURL, zastosowałem to samo podejście, ale używając atrybutu iframe srcDoc.
Poniżej przykład Reacta (wiem, że to przesada):
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 jest teraz obsługiwany w większości przeglądarek. Wygląda na to, że Edge trochę spóźnił się z jego wdrożeniem: https://caniuse.com/#feat=iframe-srcdoc
źródło
createObjectURL
jest przestarzały tylko dla argumentów MediaStream. Przekazywanie obiektu Blob nie jest przestarzałe i w rzeczywistości powoduje dość szerokie i rosnące użycie . Doceniam jednak wysiłek, aby wszystko było na bieżąco :)