2016-07-02 17 views
7

Ho bisogno di stampare un PDF ... Ma ottengo un errorestampa un pdf tramite iframe (dominio incrociato)

C'è una soluzione? Ho solo bisogno di stampare un file PDF con un solo clic

errore:

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. 

codice:

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

Beh, credo che il messaggio di errore è abbastanza descrittiva:. * Protocolli, domini e le porte devono corrispondere * 'secure.domain.com' non è la stessa come' CDN. domain.com'. –

+0

ci deve essere una soluzione alternativa – clarkk

risposta

6

L'errore si sta trattando è legato alla protezione cross-domain e la stesso- politica di origine.

Nel tuo caso, puoi stampare un iframe tra domini se annidi questo iframe in un altro iframe locale che possiamo chiamare iframe proxy.

Poiché l'iframe proxy è locale e ha la stessa origine, è possibile stamparlo senza problemi e stamperà anche l'iframe tra domini.

Vedi sotto per un esempio:

index.html (contenitore)

$(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 (proxy)

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

Con questa soluzione, non hai più trasversale problemi di dominio e puoi usare la funzione print(). Le uniche cose che devi affrontare sono un modo per trasferire l'url PDF dal contenitore al proxy e un modo per rilevare quando l'iframe con il PDF viene effettivamente caricato, ma questi dipendono dalla soluzione/lingue che stai utilizzando.

+2

questa risposta non funziona (in Chrome almeno). Sì, puoi chiamare 'print()' sul wrapper iframe, ma l'anteprima di stampa è vuota, anche se il contenuto del pdf è caricato nell'iframe interno. – jtate

+0

Qui #main indica div o iframe? – Vishnu

1

--Issue--

Hideo è giusto questo è un problema cross-domain. È una parte di CORS che è una grande cosa per la sicurezza del web ma anche un dolore.

--Philosophy--

ci sono modi per aggirare CORS ma credo che nella ricerca di una soluzione che funziona per la maggior parte di tutti i casi e continuare a utilizzarlo. Ciò semplifica il codice alla base e mantiene la coerenza del codice piuttosto che cambiare e creare codice per i casi limite. Questo può creare una soluzione iniziale più difficile ma, dato che puoi riutilizzare il metodo a prescindere dal caso d'uso, si finisce col risparmiare tempo.

--Answer--

Il modo nostro team gestisce i problemi richiesta dominio croce è bypassando completamente. CORS è qualcosa solo per i browser. Quindi il modo migliore per risolvere tutti i casi di questo problema è non dare la ragionevolezza al browser. Abbiamo il server recuperare il documento e darlo al browser sullo stesso dominio.

(Sono un ragazzo angolare) Il cliente avrebbe detto qualcosa come

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

Il server sarebbe qualcosa di simile a quello che si vede qui HTTP GET Request in Node.js Express

+0

quindi come si stampa il contenuto in formato pdf che viene restituito dal server? la domanda è come stampare un pdf nel browser, non come recuperarne uno. – jtate

1

Si tratta di una questione CORS. C'è una libreria che funge da alternativa CORS, puoi trovarla qui Xdomain CORS alternative Github.È una specie di richiesta CORS by-pass che consente di rendere efficacemente le risorse del dominio incrociato.

Ha anche Javascript, AngularJS e anche un wrapper JQuery. Penso che questo ti fornirà una soluzione più elegante, ed è semplice da integrare. Provaci .

2

C'è una soluzione per questo.

  1. Creare un endpoint nel server per restituire il contenuto HTML dell'URL esterno. (Perché non è possibile ottenere contenuti esterni dal browser - criterio dell'origine)

  2. Usa $.get per recuperare i contenuti esterni dal tuo URL e aggiungere a un iframe.

Qualcosa di simile a questo:

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 implementazione # per get-cdndomaincom-url-content:

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

+0

Grazie mille per il fascino! – Miguel

+0

Ma quando uso un URL pdf questo mostra il codice pdf codificato invece di rendere il pdf ... qualcuno ha un'idea? – Miguel

+0

@Miguel nel tuo endpoint di risposta ('get-cdndomaincom-url-content') prova a inviare il tipo MIME dell'URL nell'intestazione della risposta. Per esempio. 'Application/PDF'. Rif: http://stackoverflow.com/a/11945256/826611 –

0

Non avete bisogno di server proxy per risolvere il problema. È possibile creare iframe proxy e quindi creare dinamicamente un altro iframe all'interno dell'iframe proxy. Quindi allegare onload = "print()" ad esso.

Qualcosa di simile

/** 
    * 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(); 
    } 
Problemi correlati