2016-07-02 29 views
7

PDFを印刷する必要があります...エラーが発生します。iframe経由でpdfを印刷する(クロスドメイン)

回避策はありますか?私はちょうど1回のクリックで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'はCDN'と同じではありません。 domain.com'。 –

+0

回避策があります – clarkk

答えて

6

あなたは、クロスドメインの保護とsame-に関連して扱っているエラー起源政策。

この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()関数を使うことができます。あなたが対処する必要があるのは、コンテナからプロキシにPDF URLを渡す方法と、PDFのiframeが実際にロードされたときを検出する方法ですが、これは使用しているソリューション/言語に依存します。

+2

この回答は動作しません(少なくともChromeで)。はい、ラッパーiframeで 'print()'を呼び出すことはできますが、内側のiframeにPDFコンテンツが読み込まれていても、印刷プレビューは空白です。 – jtate

+0

ここで#mainはdivまたはiframeを表しますか? – Vishnu

1

--Issue--

秀夫が、これはクロスドメインの問題である権利です。それはウェブのセキュリティのための素晴らしいものですが、痛みもCORSの一部です。

--Philosophy--

はCORSを回避する方法がありますが、私はすべてのケースに最もために働く解決策を見つけることを信じて、それを使用し続けます。これにより、推論するコードが簡単になり、エッジケースのコードを変更したり作成するのではなく、コードの一貫性を保ちます。これにより、初期のソリューションはより難しくなりますが、ユースケースに関係なくメソッドを再利用できるため、時間が節約されます。

--Answer--

私たちのチームはそれを完全にバイパスされ、クロスドメインリクエストの問題を処理する方法。 CORSはブラウザ専用です。したがって、この問題のすべてのケースを解決する最善の方法は、ブラウザに合理性を与えないことです。サーバーはドキュメントを取り出して、同じドメインのブラウザに渡します。

(私は角度男だ) クライアントは、サーバがCORSの問題で、ここでHTTP GET Request in Node.js Express

+0

サーバーから返されるPDFコンテンツをどのように印刷しますか?問題はブラウザにPDFを印刷する方法であり、PDFを取得する方法ではありません。 – jtate

1

をあなたが見るもののようなものを持っているでしょう

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

のようなものを言うでしょう。 CORSの代替手段として機能する図書館があります。ここにはXdomain CORS alternative Githubがあります。これは、ドメイン間リソースを効果的にレンダリングするためのCORSリクエストをシームレスにバイパスします。

Javascript、AngularJS、JQueryラッパーもあります。私はこれがあなたにもっと優雅なソリューションを提供し、統合が簡単だと思います。試してみる 。

2

これを回避する方法があります。

  1. 外部URLのHTMLコンテンツを返すようにサーバーにエンドポイントを作成します。 (ブラウザからの外部コンテンツを取得することはできませんので - 同一生成元ポリシー

  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#実装を0:

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

+0

ありがとうございます。これは魅力のように機能します! – Miguel

+0

しかし、私はpdf URLを使用すると、これはPDFをレンダリングする代わりにコード化されたpdfコードを表示します...誰もがアイデアを持っていますか? – Miguel

+0

あなたのレスポンスエンドポイント( 'get-cdndomaincom-url-content')の@Miguelは、レスポンスヘッダにURLのMIMEタイプを送信してみます。例えば。 'application/pdf'です。 Ref:http://stackoverflow.com/a/11945256/826611 –

0

あなたはこの問題を回避するためにプロキシサーバーを必要としません。プロキシiframeを作成して、プロキシiframe内に別のiframeを動的に作成することができます。次に、onload = "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(); 
    } 
関連する問題