88

So here my problem: I have a pdf file as a base64 String that i am getting from the server. I would like to use this string to either display the PDF directly to the browser or give it a option of "Save as..." when clicking on a link. Here the code i am using:

<!doctype>
<html>
<head>
   <title>jsPDF</title>
   <script type="text/javascript" src="../libs/base64.js"></script>
   <script type="text/javascript" src="../libs/sprintf.js"></script>
   <script type="text/javascript" src="../jspdf.js"></script>

       <script type="text/javascript">

        function demo1() {
            jsPDF.init();
            jsPDF.addPage();
            jsPDF.text(20, 20, 'Hello world!');
            jsPDF.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');

            // Making Data URI
            var out = jsPDF.output();
            var url = 'data:application/pdf;base64,' + Base64.encode(out);

            document.location.href = url;
         }
    </script>
</head>
<body>

<a href="javascript:demo1()">Run Code</a>

</body>
</html>

Its working fine with Chrome and Safari. Firefox does recognize the pdf but does not display it as FF requires extensions to be present but the data-URI has none in this case. The reason I'm insisting here, if chrome and safari get it to work, then there has to be a solution for FF and IE

I know there are a few relevant questions to this but not really the exact one and now also a bit old ones. I know a workaround would be to have the pdf generated at server side but I would like to generate it at client side.

So please intelligent folks, is it possible through some hacks or additional JS download plugins?

5
  • 1
    hellow ??? isnt there anybody out thr who has some answer to tht .. may be john resig ;-) Commented Jul 11, 2012 at 7:56
  • @owsata, same problem here! It just opens the window! Did you find a solution to your problem? Please let us know. Thanks Commented Dec 13, 2012 at 18:09
  • 1
    @FabioMilheiro Nope didnt find anything useful. The ultimate result was that because the browsers handle the data:application idea differently there wasnt much using it in the first place. So last resort -> send a readymade pdf from the server. Commented Dec 20, 2012 at 13:06
  • Possible duplicate of Saving Base64 encoded PDF with Internet Explorer 10 and below Commented Apr 19, 2017 at 16:51
  • 1
    stackoverflow.com/a/16245768/7282741 This one solved my problem and saved my weekend. Commented Jun 5, 2017 at 5:30

8 Answers 8

83

you can use this function to download file from base64.

function downloadPDF(pdf) {
  const linkSource = `data:application/pdf;base64,${pdf}`;
  const downloadLink = document.createElement("a");
  const fileName = "abc.pdf";
  downloadLink.href = linkSource;
  downloadLink.download = fileName;
  downloadLink.click();
}

This code will made an anchor tag with href and download file. if you want to use button then you can call click method on your button click.

i hope this will help of you thanks

Sign up to request clarification or add additional context in comments.

1 Comment

I think it could be useful to mention that this probably does not work nowadays if there is no user interaction activity (like a real click). You still need that the user clicks on something to activate this.
58

You can create an anchor like the one showed below to download the base64 pdf:

<a download="PDF Title" href="pdfData">Download PDF document</a>

where pdfData is your base64 encoded pdf like:

data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nO1cyY4ktxG911fUWUC3kjsTaBTQ1Ytg32QN4IPgk23JMDQ2LB/0+2YsZAQzmZk1PSPIEB...

3 Comments

your this information helped me to accomplished it in Salesforce Lightning, using this string you can make a file download on button click
in C# when you return a FileContentResult it keeps the file encoded in base64 however there are no indications of it and no mime type.. so in order to implement it properly in the client side I had to append data:application/pdf;base64, in front of the string and it worked!
this helped me avoid creating an extra backend endpoint just to download the file, thanks!!
27

You should be able to download the file using

window.open("data:application/pdf;base64," + Base64.encode(out));

2 Comments

Nope, Chrome and FF download it directly but dont assign an extension. Safari opens the PDF and displays it in browser wow. IE opens a new tab with the title "application/octet-stream" and nothing else...
I did a straight redirect using the data structure, however it needs a container or a mechanism to parse the data into a usable format (for example: an iFrame). I have not however tested this mechanism as prescribed.
21

function dataURItoBlob(dataURI) {
      const byteString = window.atob(dataURI);
      const arrayBuffer = new ArrayBuffer(byteString.length);
      const int8Array = new Uint8Array(arrayBuffer);
      for (let i = 0; i < byteString.length; i++) {
        int8Array[i] = byteString.charCodeAt(i);
      }
      const blob = new Blob([int8Array], { type: 'application/pdf'});
      return blob;
    }

// data should be your response data in base64 format

const blob = this.dataURItoBlob(data);
const url = URL.createObjectURL(blob);

// to open the PDF in a new window
window.open(url, '_blank');

Comments

18

I know this question is old, but also wanted to accomplish this and came across it while looking. For internet explorer I used code from here to save a Blob. To create a blob from the base64 string there were many results on this site, so its not my code I just can't remember the specific source:

function b64toBlob(b64Data, contentType) {
    contentType = contentType || '';
    var sliceSize = 512;
    b64Data = b64Data.replace(/^[^,]+,/, '');
    b64Data = b64Data.replace(/\s/g, '');
    var byteCharacters = window.atob(b64Data);
    var byteArrays = [];

    for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    }

    var blob = new Blob(byteArrays, {type: contentType});
    return blob;

Using the linked filesaver:

if (window.saveAs) { window.saveAs(blob, name); }
    else { navigator.saveBlob(blob, name); }

2 Comments

Filesaver fails in Safari also :(
i posted the solution on this link stackoverflow.com/questions/34436133/… which is working fine in IE , CHROME , FF . If this solution helps you , try to vote it up
2

You will do not need any library for this. JavaScript support this already. Here is my end-to-end solution.

const xhr = new XMLHttpRequest();
xhr.open('GET', 'your-end-point', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.responseType = 'blob';
xhr.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
       if (window.navigator.msSaveOrOpenBlob) {
           window.navigator.msSaveBlob(this.response, "fileName.pdf");
        } else {
           const downloadLink = window.document.createElement('a');
           const contentTypeHeader = xhr.getResponseHeader("Content-Type");
           downloadLink.href = window.URL.createObjectURL(new Blob([this.response], { type: contentTypeHeader }));
           downloadLink.download = "fileName.pdf";
           document.body.appendChild(downloadLink);
           downloadLink.click();
           document.body.removeChild(downloadLink);
        }
    }
};
xhr.send(null);

This also work for .xls or .zip file. You just need to change file name to fileName.xls or fileName.zip. This depends on your case.

Comments

1

This worked for me:

const downloadLink = document.createElement("a")
downloadLink.href = 'data:application/octet-stream;base64,' + yourBase64Data
downloadLink.download = "convertedPDFFile.pdf"
downloadLink.click()

Comments

0

You have two ways to embed PDF on the HTML page:

#1. Iframe

<iframe id="pdf_container" src="data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwv..."></iframe>

#2. Embed

<embed id="pdf_container" src="data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwv..."></embed>

Geted from embed PDF to HTML

I suggest using one place for "data:application/pdf;base64..." to save the page size and get data to download if needed from this place.

And JS to download content:

function download()
{
   var container = document.getElementById("pdf_container");

   var download_anchor = document.createElement("a")
   download_anchor.href = container.src; 
   download_anchor.download = "file.pdf"
   download_anchor.click();
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.