Google Chrome - PDF Download in an iFrame not working
Asked Answered
L

2

7

So due to the recent Chrome update preventing a data URL from being opened directly using javaScript: "Not allowed to navigate top frame to data URL", I have some code that I need to modify. I have an ajax call that uses mPDF to generate a PDF, sends it back base 64 - and should open in a new tab. This always worked. However due to this issue, what I'm now trying to do is load that PDF into an iFrame in a new window to avoid the error. And that works, here's what I have:

$('.print-order-pdf').click(function(){

    var orderNumber = $(this).attr('order')
    var data = {
        pdfnonce: pdfAjax.pdfnonce,  
        action: 'getOrderPDF',
        orderNumber: orderNumber,
    }
    var win = window.open('', '_blank');
    $.post(pdfAjax.ajax_url, data, function(return_url){           
        win.document.write("<iframe id='pdf' src='"+ return_url +"'></iframe>");
        win.document.write("<style> html, body{ overflow:hidden; margin:0; } #pdf{ width:100%; height: 100%; }</style>");
    });

});

(This is a wordPress Ajax call). In any case - it all works and the new page with PDF opens. The problem is - in Chrome, the download link that appears as part of the PDF controls no longer works. I can print, rotate, whatever - but not download the file. I've tested in firefox, no issue triggering the download there. The Chrome console for the PDF window shows no errors at all. Any ideas? Is there something specific in Chrome preventing the download from inside the iFrame? Why? Is there a way around it?

Thanks so much in advance.

Lawson answered 29/8, 2017 at 19:41 Comment(4)
I can't reproduce this (60 stable and 62 canary, mac).Roentgenogram
Hmmm... Okay interesting - I'm using 60 stable as well and have had others here try - they're seeing the same issue. So it must be something wrong with the way I'm triggering this tab - but I don't know what. Attached is a screenshot of the inspector. Nothing in the console, this is what the embed and download icon look like. Is there something off here? screencast.com/t/WlqHqJTJ50KLawson
Have you found any solution?Gretta
Does this answer your question? JsPDF - Not allowed to navigate top frame to data URLKenishakenison
C
3

My scenario is exactly that! I'm using chrome version 61.0.3163.100. I guess it's some browser flaw, but I did not find anything on google's forums. I am in doubt whether to download the file directly but would not want to give up the chrome PDF viewer.

Temporarily, I have found an ugly and inelegant solution until I have a definitive answer. I created a link in the generated window:

var newWindow = window.open("", "PDF", 'dependent=yes,locationbar=no,scrollbars=no,menubar=no,resizable,screenX=50,screenY=50,width=850,height=800');
newWindow.document.write(
'<html><body><center>' +
'<a title="Download File" style="font-family: \'Verdana\';color: #333;text-decoration: none;font-weight: 600;" download="File.PDF" href="data:application/pdf;base64,' + base64 + '">Download File</a>' +
'</center><br>' +
'<object width=100% height=100% type="application/pdf" data="data:application/pdf;base64,' + base64  + '">' +
'<embed type="application/pdf" src="data:application/pdf;base64,' + base64  + '" id="embed_pdf"></embed>' +
 '</object></body></html>');
 newWindow.window.focus();
Castera answered 24/10, 2017 at 15:40 Comment(2)
Have you found any elegant solution? :)Gretta
Nop. I changed approach and download the file, it's much cleaner and more compatible. I convert base64 to a blob, create a link element in memory with the blob and I download itCastera
L
0

To support downloading, the Chrome PDF viewer needs a reference to the PDF content in memory. To provide this reference:

  1. Download the PDF content into a JavaScript blob.
  2. Call createObjectURL() on the blob.
  3. Use the object URL as the source of the iframe (or data= of the object tag).

Here is an example, combining the original post with some code to download into a blob:

$('.print-order-pdf').click(function(){
  // Code from the original post.
  var orderNumber = $(this).attr('order')
  var data = {
    pdfnonce: pdfAjax.pdfnonce,  
    action: 'getOrderPDF',
    orderNumber: orderNumber,
  }
  var win = window.open('', '_blank');

  $.post(pdfAjax.ajax_url, data, function(return_url){ 
    // Download the PDF content into blob.             
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var url = win.URL || win.webkitURL;

        // Create the object URL.
        var objectUrl = url.createObjectURL(this.response);

        // Use the object URL as the source of the iframe.
        win.document.write("<iframe id='pdf' src='"+ objectUrl +"'></iframe>");

        win.document.write("<style> html, body{ overflow:hidden; margin:0; } #pdf{ width:100%; height: 100%; }</style>");
      }
    };
    xhr.open('GET', returnUrl);
    xhr.responseType = 'blob';  // Response will be a blob.
    xhr.send();
  });
});
Lili answered 14/6, 2024 at 23:24 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.