Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decode Base64 encoded PDF content in browser

We transform HTML to PDF in the backend (PHP) using dompdf. The generated output from dompdf is Base64 encoded with

$output = $dompdf->output();
base64_encode($output);

This Base64 encoded content is saved as a file on the server. When we decode this file content like this:

cat /tmp/55acbaa9600f4 | base64 -D > test.pdf

we get a proper PDF file.

But when we transfer the Base64 content to the client as a string value inside a JSON object (the server provides a RESTful API...):

{
  "file_data": "...the base64 string..."
}

And decode it with atob() and then create a Blob object to download the file later on, the PDF is always "empty"/broken.

$scope.downloadFileData = function(doc) {
  DocumentService.getFileData(doc).then(function(data) {
    var decodedFileData = atob(data.file_data);
    var file = new Blob([decodedFileData], { type: doc.file_type });
    saveAs(file, doc.title + '.' + doc.extension);
  });
};

When we log the decoded content, it seems that the content is "broken", because several symbols are not the same as when we decode the content on the server using base64 -D.

When we encode/decode the content of simple text/plain documents, it's working as expected. But all binary (or not ASCII formats) are not working.

We have searched the web for many hours, but didn't find a solution for this that works for us. Does anyone have the same problem and can provide us with a working solution? Thanks in advance!

This is a example for a on the server Base64 encoded content of a PDF document:

JVBERi0xLjMKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2VzIDMgMCBSID4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcyAvQ291bnQgMCA+PgplbmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzYgMCBSCl0KL0NvdW50IDEKL1Jlc291cmNlcyA8PAovUHJvY1NldCA0IDAgUgovRm9udCA8PCAKL0YxIDggMCBSCj4+Cj4+Ci9NZWRpYUJveCBbMC4wMDAgMC4wMDAgNjEyLjAwMCA3OTIuMDAwXQogPj4KZW5kb2JqCjQgMCBvYmoKWy9QREYgL1RleHQgXQplbmRvYmoKNSAwIG9iago8PAovQ3JlYXRvciAoRE9NUERGKQovQ3JlYXRpb25EYXRlIChEOjIwMTUwNzIwMTMzMzIzKzAyJzAwJykKL01vZERhdGUgKEQ6MjAxNTA3MjAxMzMzMjMrMDInMDAnKQo+PgplbmRvYmoKNiAwIG9iago8PCAvVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9Db250ZW50cyA3IDAgUgo+PgplbmRvYmoKNyAwIG9iago8PCAvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDY2ID4+CnN0cmVhbQp4nOMy0DMwMFBAJovSuZxCFIxN9AwMzRTMDS31DCxNFUJSFPTdDBWMgKIKIWkKCtEaIanFJZqxCiFeCq4hAO4PD0MKZW5kc3RyZWFtCmVuZG9iago4IDAgb2JqCjw8IC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovTmFtZSAvRjEKL0Jhc2VGb250IC9UaW1lcy1Cb2xkCi9FbmNvZGluZyAvV2luQW5zaUVuY29kaW5nCj4+CmVuZG9iagp4cmVmCjAgOQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDggMDAwMDAgbiAKMDAwMDAwMDA3MyAwMDAwMCBuIAowMDAwMDAwMTE5IDAwMDAwIG4gCjAwMDAwMDAyNzMgMDAwMDAgbiAKMDAwMDAwMDMwMiAwMDAwMCBuIAowMDAwMDAwNDE2IDAwMDAwIG4gCjAwMDAwMDA0NzkgMDAwMDAgbiAKMDAwMDAwMDYxNiAwMDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDkKL1Jvb3QgMSAwIFIKL0luZm8gNSAwIFIKPj4Kc3RhcnR4cmVmCjcyNQolJUVPRgo=

If you atob() this, you don't get the same result as on the console with base64 -D. Why?

like image 369
Marcel Härle Avatar asked Jul 20 '15 10:07

Marcel Härle


People also ask

Can browser decode Base64?

Encoding and Decoding Strings with Base64 btoa() and atob() are two Base64 helper functions that are a core part of the HTML specification and available in all modern browsers.

How do I decode a Base64 encoded file?

To decode a file with contents that are base64 encoded, you simply provide the path of the file with the --decode flag. As with encoding files, the output will be a very long string of the original file. You may want to output stdout directly to a file.


2 Answers

Your issue looks identical to the one I needed to solve recently.

Here is what worked for me:

const binaryImg = atob(base64String);
const length = binaryImg.length;
const arrayBuffer = new ArrayBuffer(length);
const uintArray = new Uint8Array(arrayBuffer);

for (let i = 0; i < length; i++) {
    uintArray[i] = binaryImg.charCodeAt(i);
}

const fileBlob = new Blob([uintArray], { type: 'application/pdf' });

saveAs(fileBlob, 'filename.pdf');

It seems that only doing a base64 decode is not enough...you need to put the result into a Uint8Array. Otherwise, the pdf pages appear blank.

I found this solution here: https://github.com/sayanee/angularjs-pdf/issues/110#issuecomment-579988190

like image 88
mezoid Avatar answered Sep 22 '22 16:09

mezoid


You can use btoa() and atob() work in some browsers: For Exa.

var enc = btoa("this is some text");
alert(enc);
alert(atob(enc));

To JSON and base64 are completely independent.

Here's a JSON stringifier/parser (and direct GitHub link).

Here's a base64 Q&A. Here's another one.

like image 44
Bhavin Solanki Avatar answered Sep 23 '22 16:09

Bhavin Solanki