2016-07-02 6 views
7

Мне нужно распечатать PDF ... Но я получаю сообщение об ошибкераспечатать pdf через iframe (перекрестный домен)

Есть ли обходной путь? Мне просто нужно напечатать файл PDF одним щелчком мыши

ошибка:

Uncaught SecurityError: Blocked a frame with origin "https://secure.domain.com" from accessing a frame with origin "https://cdn.domain.com". Protocols, domains, and ports must match. 

код:

var iframe = $('<iframe src="'+url+'" style="display:none"></iframe>').appendTo($('#main')).load(function(){ 
    iframe.get(0).contentWindow.print(); 
}); 
+0

Ну, я считаю, что сообщение об ошибке весьма описательный:. * Протоколы, домены и порты должны соответствовать * 'secure.domain.com' не то же самое, как' КДС. domain.com'. –

+0

должно быть обходное решение – clarkk

ответ

6

Ошибка вы имеете дело с связано с защитой междоменном и кампанией с таким же происхождения.

В вашем случае вы можете распечатать междоменное iframe, если вы вставляете этот iframe в другой локальный iframe, который мы можем назвать прокси iframe.

Поскольку прокси-сервер iframe является локальным и имеет одинаковое происхождение, вы можете распечатать его без каких-либо проблем, а также распечатать междоменное iframe.

Ниже для примера:

index.html (контейнер)

$(function() { 
    var url = 'proxy.html'; // We're not loading the PDF but a proxy which will load the PDF in another iframe. 

    var iframe = $('<iframe src="' + url + '"></iframe>').appendTo($('#main')); 

    iframe.on('load', function(){ 
    iframe.get(0).contentWindow.print(); 
    }); 
}); 

proxy.html (прокси)

<body> 
    <iframe src="http://ANOTHER_DOMAIN/PDF_NAME.pdf"></iframe> 
</body> 

С помощью этого решения, вы больше не кросс- и вы можете использовать функцию print(). Единственное, с чем вам нужно иметь дело, - это способ передать URL-адрес PDF из контейнера в прокси-сервер и способ обнаружить, когда iframe с PDF-файлом загружен, но это зависит от используемого вами решения/языков.

+2

Этот ответ не работает (по крайней мере, в Chrome). Да, вы можете вызывать 'print()' на обертке iframe, но предварительный просмотр печати пуст, даже если содержимое pdf загружено во внутренний iframe. – jtate

+0

Здесь #main обозначает div или iframe? – Vishnu

1

--Issue--

Hideo правильно это вопрос междоменное. Это часть CORS, которая является отличной вещью для безопасности в Интернете, но также и для боли.

--Philosophy--

Есть способы обойти CORS, но я считаю, в поиске решения, которое работает для большинства во всех случаях и продолжать использовать его. Это создает более простой код, чтобы рассуждать о том, что код совместим, а не меняет и создает код для краевых случаев. Это может создать более сложное первоначальное решение, но поскольку вы можете повторно использовать этот метод, независимо от используемого варианта, вы в конечном итоге сэкономите время.

--Answer--

То, как наша команда обрабатывает перекрестные вопросы запроса домена полностью в обход его. CORS - это что-то для браузеров. Таким образом, лучший способ решить все случаи этой проблемы - не дать разумности браузеру. У нас есть сервер, который извлекает документ и передает его браузеру в том же домене.

(я угловой парень) клиент хотел бы сказать что-то вроде

$http.get('/pdf/x').then(function(){ 
    //do whatever you want with any cross-domain doument 
}); 

Сервера будет иметь что-то вроде того, что вы видите здесь HTTP GET Request in Node.js Express

+0

Итак, как бы вы напечатали pdf-контент, который возвращается с сервера? вопрос заключается в том, как печатать PDF в браузере, а не как его получить. – jtate

1

Это вопрос CORS. Существует библиотека, которая действует как альтернатива CORS, вы можете найти ее здесь Xdomain CORS alternative Github.Это своего рода обход CORS без проблем, чтобы эффективно перекрестно использовать ресурсы домена.

У этого есть Javascript, AngularJS, а также обертка JQuery. Я думаю, что это предоставит вам более элегантное решение и просто интегрируется. Попробуйте.

2

Существует обходное решение для этого.

  1. Создайте конечную точку на своем сервере, чтобы вернуть содержимое HTML внешнего URL-адреса. (Потому что вы не можете получить внешнее содержимое из браузера - того же происхождение политика)

  2. Использование $.get для извлечения внешнего контента с вашего URL и добавьте его в iframe.

Что-то похожее на это:

HTML:

<div id="main"> 
    <iframe id="my-iframe" style="display:none"></iframe> 
</div> 

JS: реализация

$.get('https://secure.domain.com/get-cdndomaincom-url-content', function(response) { 
    var iframe = $('#my-iframe')[0], 
     iframedoc = iframe.contentDocument || iframe.contentWindow.document; 

    iframedoc.body.innerHTML = response; 
    iframe.contentWindow.print(); 
}); 

C# для get-cdndomaincom-url-content:

Easiest way to read from a URL into a string in .NET

+0

Спасибо, что это работает как шарм! – Miguel

+0

Но когда я использую pdf-url, это показывает кодированный pdf-код, а не рендеринг pdf ... у кого есть идея? – Miguel

+0

@Miguel в вашей конечной точке ответа ('get-cdndomaincom-url-content') попробуйте отправить MIME-тип URL-адреса в заголовке ответа. Например. 'Приложение/pdf'. Ссылка: http://stackoverflow.com/a/11945256/826611 –

0

Вам не нужно прокси-сервер для обхода. Вы можете создать прокси iframe, а затем динамически создать другой iframe внутри прокси iframe. Затем присоедините к нему loadload = "print()".

Что-то вроде этого

/** 
    * Load iframe from cross-origin via proxy iframe 
    * and then invokes the print dialog. 
    * It is not possible to call window.print() on the target iframe directly 
    * because of cross-origin policy. 
    * 
    * Downside is that the iframe stays loaded. 
    */ 
    function printIframe(url) { 
    var proxyIframe = document.createElement('iframe'); 
    var body = document.getElementsByTagName('body')[0]; 
    body.appendChild(proxyIframe); 
    proxyIframe.style.width = '100%'; 
    proxyIframe.style.height = '100%'; 
    proxyIframe.style.display = 'none'; 

    var contentWindow = proxyIframe.contentWindow; 
    contentWindow.document.open(); 
    // Set dimensions according to your needs. 
    // You may need to calculate the dynamically after the content has loaded 
    contentWindow.document.write('<iframe src="' + url + '" onload="print();" width="1000" height="1800" frameborder="0" marginheight="0" marginwidth="0">'); 
    contentWindow.document.close(); 
    } 
Смежные вопросы