60

After updating Google Chrome, the report jsPDF in a new Window does not work any more.

The console shows the message:

Not allowed to navigate top frame to data URL: data:application/pdf;base64,JVBERi0xLjMKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1....

Can you help-me?

Thanks.

Difster
  • 3,264
  • 2
  • 22
  • 32
Márcio Rossato
  • 971
  • 1
  • 11
  • 20

15 Answers15

63

This works well now that chrome has removed top frame navigation. Only downloading the pdf in chrome gives problem. Download works in well in firefox tho.

var string = doc.output('datauristring');
var iframe = "<iframe width='100%' height='100%' src='" + string + "'></iframe>"
var x = window.open();
x.document.open();
x.document.write(iframe);
x.document.close();
Joyston
  • 806
  • 8
  • 10
  • This solution worked for me very well. I'm using html2canvas. – Aaron Kreider Oct 10 '17 at 22:13
  • Worked for me on Firefox and Chrome. Needed to encodeURIComponent(string) though. – user2099484 Oct 19 '17 at 08:44
  • 1
    Then what is the solution for downloading in Chrome? – Sukanta Bala Jan 16 '18 at 12:24
  • Not sure yet. I'll post the solution if I find any @SukantaBala If someone finds any then please post. I'll upvote it. – Joyston Jan 16 '18 at 18:37
  • 3
    @SukantaBala As of now this is how I have handled the download issue. doc.save(filename + '.pdf'); This code automatically downloads the pdf without having to click the download button. – Joyston Jan 16 '18 at 18:46
  • It's important to use the 'datauristring' option, other options, although may return a datauri, will also open windows and may cause console errors, works well though. – PeterS Feb 15 '18 at 11:41
  • @Joyston do you call this as well as open the PDF in an iframe? – NorCalKnockOut Mar 13 '18 at 23:37
  • 1
    Yes @NorCalKnockOut. Atleast for my purpose I needed to view the pdf so I had to open it in an iframe. You could directly save on your local machine as well by using doc.save(filename + '.pdf'); – Joyston Mar 20 '18 at 11:22
  • @Joyston Did you ever find a solution for fixing the download button in Chrome? – Carsten Dec 29 '19 at 13:49
  • using this method, little download icon doesnt work, user can only see the document and cannot save it, anyone else facing the same? – Inzamam Malik May 18 '21 at 08:28
  • You should also set `frameborder` to 0 and `style` to `margin: 0`. – Caleb Liu Jul 07 '22 at 13:12
  • Also, this solution has the url in the url box on `about:blank`. Is there a way to change the url to the data url, possibly without navigating? – Caleb Liu Jul 09 '22 at 12:19
40

Apparently Google Chrome has removed support for top-frame navigation, you can see more informations here: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/GbVcuwg_QjM

You may try to render the jsPDF to an iFrame

Pedro Calderon
  • 457
  • 4
  • 7
18

I recently had the same problem using FileReader object to read content and show my JSReport.

 var reader = new FileReader();                        
 reader.onload = function (e) {
      window.open(reader.result, "_blank");
 }
 reader.readAsDataURL(blob);

Unfortunatly after chrome update all my report stopped working. I tried to fix this by using Blob object and it's still working but if you have a popup blocker it will not work.

 var file = new Blob([blob], { type: 'application/pdf' });
 var fileURL = URL.createObjectURL(file);
 window.open(fileURL);

I finally find a way to avoid this problem by creating the iFrame dynamically after reading this topic and i decided to share the solution.

 var file = new Blob([blob], { type: 'application/pdf' });
 var fileURL = URL.createObjectURL(file);
 var win = window.open();
 win.document.write('<iframe src="' + fileURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>')
Sadek Lallouani
  • 201
  • 1
  • 4
11

Maybe can help, create a function to export with the download attribute html5:

var docPdf = doc.output();
exportToFile(docPdf,defaults.type);

function exportToFile(data,type){

    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/'+type+';filename='+'exportar.'+type+';'+'charset=utf-8,' + encodeURI(data);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'exportar.'+type;
    hiddenElement.click();
}
Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53
nikoz84
  • 133
  • 1
  • 8
4

the download property of the a element has to contain a file name.

function window_download( datauri )
{
  const match = datauri.match(/(filename=)([^;]+)/);
  const fileName = match ? match[2] : '' ;
  if ( fileName )
  {
    const downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    downloadLink.innerHTML = "Download File";
    downloadLink.href = datauri ;
    downloadLink.click();
  }
else
{
throw 'missing download file name' ;
}


   // get contents of pdf from jsPDF as a data uri.
    const uri = pdf.output('datauristring', 'packing-list.pdf' );
    window_download( uri ) ;

RockBoro
  • 2,163
  • 2
  • 18
  • 34
3

As chrome removed its support for - Top-frame navigation. Luckily jsPDF has an API - "save()", which offers the same functionality as doc.output('datauri')

Below is the example implementation of save()

var doc = new jsPDF();
doc.addImage(imgData, 'JPEG', 0, 0, 300, 160);    
doc.save('fileName.pdf');

save(filename, options) → {jsPDF|Promise}

Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf'). Uses FileSaver.js-method saveAs. Refer JSPDF documentation for more information -

Satheesh K
  • 132
  • 2
  • 16
2
<iframe id="ManualFrame"
        frameborder="0"
        style="border:0"
        allowfullscreen>
</iframe>

<script>
    $(function () {
        setManualFrame();
    });

    function setManualFrame() {
        $("#ManualFrame").attr("height", screen.height);
        $("#ManualFrame").attr("width", screen.width);
        $("#ManualFrame").attr("src", "data:application/pdf;base64," + Your_PDF_Data);
    }
</script>
Lonely Planeteer
  • 389
  • 1
  • 5
  • 21
2
var pdfUrl = doc.output('datauri').substring(doc.output('datauri').indexOf(',')+1);
var binary = atob(pdfUrl.replace(/\s/g, ''));
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
    view[i] = binary.charCodeAt(i);
}

var blob = new Blob( [view], { type: "application/pdf" });
var url = URL.createObjectURL(blob);

function openPDF(){
    window.open(url);
}
Surya T
  • 31
  • 2
  • 1
    Can you please explain how this solves the original question? – Brett DeWoody Dec 17 '17 at 23:33
  • you can use this code to open the pdf document in a new tab as a blob... cause chrome blocks JsPDF from opening the document.... which i believe is the original question. – Surya T Dec 18 '17 at 12:12
2

Add attrbute download

<a href="data:image/jpg;base64,/AA/AABBCCDD..." download="name.jpg"></a>
Jhonattan
  • 372
  • 3
  • 13
1

@kuldeep-choudhary

Hi, in fact, to solve i'm using object tag with angularJS 1.5.xx

<object ng-attr-data="{{data}}" type="application/pdf"></object>

and in script:

$scope.doc.data = $sce.trustAsResourceUrl(doc.output("datauristring"));

In pure javascript, maybe like this works:

html:

<object id="obj" type="application/pdf" ></object>

js:

document.elementById('obj').data = doc.output("datauristring");

please, try and correct-me if I wrong.

Márcio Rossato
  • 971
  • 1
  • 11
  • 20
1

Based on Joyston's answer, but without reparsing and therefore without additional need to escape something:

x=window.open();
iframe=x.document.createElement('iframe')
iframe.width='100%'
iframe.height='100%'
iframe.frameBorder=0
iframe.style="border: 0"
iframe.src='data:text/html........' //data-uri content here
x.document.body.appendChild(iframe);
T S
  • 1,656
  • 18
  • 26
1

Not related to jspdf, but did help me here (and this question is the top hit at google): If specifying a download="..." attribute to the anchor tag, the download prompt will properly open up.

phil294
  • 10,038
  • 8
  • 65
  • 98
1

Using download="" made me able to download the file

vimuth
  • 5,064
  • 33
  • 79
  • 116
1
/**
 * Creates an anchor element `<a></a>` with
 * the base64 pdf source and a filename with the
 * HTML5 `download` attribute then clicks on it.
 * @param  {string} pdf 
 * @return {void}     
 */
function downloadPDF(pdf) {
    const linkSource = `data:application/pdf;base64,${pdf}`;
    const downloadLink = document.createElement("a");
    const fileName = "vct_illustration.pdf";

    downloadLink.href = linkSource;
    downloadLink.download = fileName;
    downloadLink.click();
}

Source from: https://medium.com/octopus-labs-london/downloading-a-base-64-pdf-from-an-api-request-in-javascript-6b4c603515eb

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
0

In angular2+ -

app.component.html -

 <object id="obj"  [attr.data]  type="application/pdf"> </object>

app.component.ts

 document.getElementById('obj').dataset.data = doc.output("datauristring");

  var blob = doc.output("blob");
  window.open(URL.createObjectURL(blob));
Techdive
  • 997
  • 3
  • 24
  • 49