Print pdf via iframe (cross domain)

I need to print a PDF ... But I get an error

Is there a workaround? I just need to print a PDF file with one click

Mistake:

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. 

the code:

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

The error you are dealing with is related to cross-domain protection and policies of the same origin.

In your case, you can print the cross-domain iframe if you embed this iframe in another local iframe, which we can call the iframe proxy.

Since the proxy iframe is local and has the same origin, you can print it without any problems, as well as print the cross-domain iframe.

The following is an example:

index.html (container)

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

With this solution, you no longer have cross-domain access issues, and you can use the print () function. The only thing you need to deal with is to transfer the PDF URL from the container to the proxy server and determine when the iframe with the PDF file is really loaded, but it depends on the solution / languages ​​you use.

+5
source share

There is a workaround for this.

  • Create an endpoint on your server to return the HTML content of the external URL. (because you cannot get external content from browser policies of the same origin)

  • Use $.get to extract external content from your URL and add it to the iframe .

Something like this:

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 # implementation for get-cdndomaincom-url-content :

Easiest way to read from url to string in .NET

+2
source share

- Issue -

HiDeo is right, this is a cross-domain access issue. This is part of CORS , which is a great thing for Internet security, but also for pain.

- Philosophy -

There are ways to get around CORS, but I believe that you will find a solution that works for most cases and will continue to use it. This creates simpler code to reason that the code is compatible, rather than changing and creating code for edge cases. This may create a more complicated initial solution, but since you can reuse this method regardless of the case used, you will end up saving time.

- the answer is -

The way our team handles problems with cross-domain requests completely circumvents it. CORS is something for browsers. Thus, the best way to solve all cases of this problem is to prevent the browser from being reasonable. We have a server that retrieves the document and passes it to the browser in the same domain.

(I'm an Angular guy) A client would say something like

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

The server will have something like what you see here HTTP GET Request in Node.js Express

+1
source share

This is a CORS problem. There is a library that acts as an alternative to CORS, you can find it here Xdomain CORS alternative to Github . This is a kind of workaround for CORS that allows you to efficiently cross-use domain resources.

It has Javascript, AngularJS, as well as a jQuery wrapper. I think this will provide you with a more elegant solution and is easy to integrate. Give it a try.

+1
source share

You do not need a proxy server to bypass. You can create an iframe proxy and then dynamically create another iframe inside the iframe proxy. Then attach toload = "print ()".

Something like that

  /** * 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(); } 
+1
source share

All Articles