3

I am trying to view a PDF saved in binary data in our SQL database using Angular and PDF.js. The data returned from the service looks like this:

enter image description here

Essentially, I believe that I need to create an objectURL for it to work, but I'm not sure how to convert it to a blob. I have tried the following:

        .success(function (response) {
        var fileName = response[0].FileName;
        var fileImage = response[0].binFileImage;
        var blob = new Blob(fileImage, { type: 'application/pdf' });
        var fileURL = URL.createObjectURL(blob);

I use the following to convert image files:

 function base64ArrayBuffer(arrayBuffer) {
    var base64 = ''
    var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

    var bytes = new Uint8Array(arrayBuffer)
    var byteLength = bytes.byteLength
    var byteRemainder = byteLength % 3
    var mainLength = byteLength - byteRemainder

    var a, b, c, d
    var chunk

    // Main loop deals with bytes in chunks of 3
    for (var i = 0; i < mainLength; i = i + 3) {
        // Combine the three bytes into a single integer
        chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]

        // Use bitmasks to extract 6-bit segments from the triplet
        a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
        b = (chunk & 258048) >> 12 // 258048   = (2^6 - 1) << 12
        c = (chunk & 4032) >> 6 // 4032     = (2^6 - 1) << 6
        d = chunk & 63               // 63       = 2^6 - 1

        // Convert the raw binary segments to the appropriate ASCII encoding
        base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
    }

    // Deal with the remaining bytes and padding
    if (byteRemainder == 1) {
        chunk = bytes[mainLength]

        a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2

        // Set the 4 least significant bits to zero
        b = (chunk & 3) << 4 // 3   = 2^2 - 1

        base64 += encodings[a] + encodings[b] + '=='
    } else if (byteRemainder == 2) {
        chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]

        a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
        b = (chunk & 1008) >> 4 // 1008  = (2^6 - 1) << 4

        // Set the 2 least significant bits to zero
        c = (chunk & 15) << 2 // 15    = 2^4 - 1

        base64 += encodings[a] + encodings[b] + encodings[c] + '='
    }

    return base64
}

I tried using it for the PDF, but I'm not sure if that is the correct format. The above function converts the byte array to:

JVBERi0xLjQNCiX5+prnDQo3IDAgb2JqDQo8PA0KL0UgMzU0ODENCi9IIFsgMTM3OCAxNjMgXQ0KL0wgMzc3NzkNCi9MaW5lYXJpemVkIDENCi9OIDINCi9PIDEwDQovVCAzNzU4OQ0KPj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmVuZG9iag0KDQp4cmVmDQo3IDExDQowMDAwMDAwMDE3IDAwMDAwIG4NCjAwMDAwMDEyN... (shortened).

I'm not really sure what I need to do to convert the data so that I can use it to create an object url so that I can view the pdf. Any assistance is greatly appreciated!

2
  • For Blob you need array of arrays, e.g. var blob = new Blob([fileImage], { type: 'application/pdf' });. Also pdf.js can consume binary data array as input too. Commented Apr 19, 2016 at 17:00
  • I tried that it throws an InvalidStateError. It seems fileImage must be converted to something else first, but I don't know what or how. Commented Apr 19, 2016 at 17:06

2 Answers 2

16

There is probably an easier way to do this, but this works in IE and Chrome.

  1. First, I converted the byte array to base64.
  2. Next I converted the base64 to a Uint8Array.
  3. Then I display the file.

Here is the code that worked for me:

    lwsService.getdocument(id)
    .success(function (response) {
       var byteArray = new Uint8Array(response[0].binFileImage);
       var blob = new Blob([byteArray], { type: 'application/pdf' });
        if (window.navigator && window.navigator.msSaveOrOpenBlob) {
          window.navigator.msSaveOrOpenBlob(blob);
        } else {
          var objectUrl = URL.createObjectURL(blob);
          window.open(objectUrl);
        }

I hope this helps someone else.

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

4 Comments

can you just do new Uint8Array(response[0].binFileImage) ?
For me, the current answer didn't work, but the edited one (with all the arrays) helped me a lot.Thanks !
What data type is 'response[0].binFileImage' ?
@SomeRandomDeveloper - its a BLOB from SQL database
1

Try the following example. it's using FileSaver.

var blob = new Blob([content], {type: 'application/octet-stream'});
saveAs(blob, "yourFile.pdf");

1 Comment

I'm not trying to save the file. I'm trying to view it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.