Có thể thêm Tiêu đề Yêu cầu vào một yêu cầu src iframe không?


82

Tôi hiểu rằng bạn có thể đặt tiêu đề yêu cầu HTTP rất dễ dàng khi thực hiện lệnh gọi AJAX trong JavaScript.

Tuy nhiên, có thể đặt tiêu đề yêu cầu HTTP tùy chỉnh khi chèn iframe vào một trang thông qua tập lệnh không?

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

Câu trả lời:


31

Không, bạn không thể. Tuy nhiên, bạn có thể đặt iframenguồn thành một số loại tập lệnh tải trước, tập lệnh này sử dụng AJAX để tìm nạp trang thực tế với tất cả các tiêu đề bạn muốn.


4
Hi Niết, bạn có thể vui lòng cung cấp mã thực hiện mẫu trong JSFiddle
Naveen Reddy

Tôi tin rằng Niet có nghĩa là một cái gì đó như thế này stackoverflow.com/a/17695034/1524918
Ryan Kara

5
Yêu cầu trong một tập lệnh tải trước như vậy sẽ không được gửi đến một miền khác và do đó vi phạm Chính sách nguồn gốc giống nhau?
mart1n

Tiêu đề nào được gửi theo mặc định? Có tiêu chuẩn nào về điều đó không?
Vụ kiện của Fund Monica vào

74

Bạn có thể thực hiện yêu cầu bằng javascript, đặt bất kỳ tiêu đề nào bạn muốn. Sau đó, bạn có thể URL.createObjectURL(), để có được thứ gì đó phù hợp với 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 :(');
    }
  }
}

Kiểu MIME của phản hồi được giữ nguyên. Vì vậy, nếu bạn nhận được phản hồi html, html sẽ hiển thị trong iframe. Nếu bạn yêu cầu một pdf, trình xem pdf của trình duyệt sẽ kích hoạt iframe.

Nếu đây là một phần của ứng dụng phía máy khách đã tồn tại lâu, bạn có thể muốn sử dụng URL.revokeObjectURL()để tránh rò rỉ bộ nhớ.

Các URL đối tượng cũng khá thú vị. Chúng có hình thức blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. Bạn thực sự có thể mở chúng trong một tab mới và xem phản hồi và chúng sẽ bị loại bỏ khi ngữ cảnh tạo ra chúng bị đóng.

Đây là một ví dụ đầy đủ: https://github.com/courajs/pdf-poc


Hoàn hảo. Làm việc hoàn hảo. Cảm ơn bạn.
mike123 22/09/17

bạn là người đàn ông! Tôi đang làm việc trên một thành phần Angular 5 được lấy cảm hứng từ mã này để hiển thị bản xem trước pdf trong Angularjs. điều này đã giúp tôi rất nhiều
FireDragon

Cảm ơn bạn! Ông đã cứu vớt đời tôi!
Renato Souza de Oliveira

1
@BSSchwarzkopf có vẻ như bạn đã đúng. Các URL khối được hỗ trợ trong Edge, nhưng chúng sẽ không hoạt động trong thuộc tính src của iframe. Tôi coi đó là sự vi phạm thông số kỹ thuật: "Lược đồ này có thể được sử dụng với các API web ... và với các phần tử được thiết kế để sử dụng với các URL HTTP ... Nói chung, lược đồ này phải được thiết kế để được sử dụng ở bất cứ nơi nào có thể sử dụng URL trên web. " Sự cố trên trình theo dõi Edge: developer.microsoft.com/en-us/microsoft-edge/platform/issues/… Spec: w3.org/TR/FileAPI/#use-case-scheme
FellowMD

Tôi nhận được "Không thực hiện được 'createObjectURL' trên 'URL': Không tìm thấy hàm nào phù hợp với chữ ký được cung cấp." trên Chrome 84.0.4147.105.
poiuytrez,

2

Hóa ra URL.createObjectURL () không được dùng nữa trong Chrome 71
(xem https://developers.google.com/web/updates/2018/10/chrome-71-deps-rems )
Xây dựng trên @Niet the dark Absol và Câu trả lời tuyệt vời của @ FellowMD, đây là cách tải tệp vào iframe, nếu bạn cần chuyển các tiêu đề xác thực. (Bạn không thể chỉ đặt thuộc tính src thành 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>');
            }
        }
    }
}

và gửi lời chào tới courajs: https://github.com/courajs/pdf-poc/blob/master/script.js


1
Từ liên kết Google: "Phương thức URL.createObjectURL () đã bị xóa khỏi giao diện MediaStream." Việc ngừng sử dụng này có ảnh hưởng đến giao diện MediaStream có liên quan đến câu trả lời khác không? (Tôi nghĩ là không.)
Jared Thirsk

Không bị phản đối. Chỉ lấy ra từ MediaStream
TheMaster

1
@TheMaster đó thực sự là những gì tài liệu nói, nhưng tôi đã dành vài giờ để cố gắng làm cho nó hoạt động và không thành công. Nó không thể suy đoán tại sao. Đoạn mã hiển thị ở trên là những gì đã kết thúc hoạt động tại thời điểm tôi mã hóa nó, tôi không có băng thông để thử lại.
TomEberhard

Bạn có thể sử dụng phương pháp đó với các đối tượng Blob. Trong trường hợp của bạn, điều đó sẽ như thế nàyURL.createObjectURL(new Blob([this.response.documentElement.innerHTML]))
u.unver34

createObjectURLchỉ không được dùng cho các đối số MediaStream. Vượt qua Blob không bị phản đối, và trên thực tế , việc sử dụng khá rộng rãi và ngày càng tăng . Tôi đánh giá cao các nỗ lực để giữ cho mọi thứ đến nay mặc dù :)
FellowMD

2

Vì câu trả lời @FellowMD không hoạt động trên các trình duyệt hiện đại do sự mất giá của createObjectURL, tôi đã sử dụng phương pháp tương tự nhưng sử dụng thuộc tính iframe srcDoc.

  1. Truy xuất nội dung để hiển thị trong iframe bằng cách sử dụng XMLHttpRequest hoặc bất kỳ phương pháp nào khác
  2. Đặt tham số srcdoc của iframe

Vui lòng tìm ví dụ về React bên dưới (tôi biết nó quá mức cần thiết):

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 hiện đã được hỗ trợ trên hầu hết các trình duyệt. Có vẻ như Edge đã hơi muộn để triển khai nó: https://caniuse.com/#feat=iframe-srcdoc


createObjectURLchỉ không được dùng cho các đối số MediaStream. Vượt qua Blob không bị phản đối, và trên thực tế , việc sử dụng khá rộng rãi và ngày càng tăng . Tôi đánh giá cao các nỗ lực để giữ cho mọi thứ đến nay mặc dù :)
FellowMD
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.