2

I am trying to download a Attachment using JSForce library. I am able to get body of attachment and download that file but somehow content of downloaded file is not correct and I am getting a corrupt downloaded file.

           var conn = new jsforce.Connection({
               accessToken: `${this.sessionId}`
           });            
           let query = 'select id, body, name from attachment where id = \'00P1g000005A1mT\'';
            conn.query(query, function(err, res) {
                console.log(res.records[0]);
                if(res) {
                   conn.chatter.resource(res.records[0].Body).retrieve(function(err,body) {
                        var l = btoa(unescape(encodeURIComponent(body)));
                        var blob = new Blob(l, {type: "image/jpeg"});
                        const url = window.URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.style.display = 'none';
                        a.href = url;
                        a.download = 'todo-1.jpg';
                        document.body.appendChild(a);
                        a.click();
                        window.URL.revokeObjectURL(url);
                            alert('your file has downloaded!'); 
                    })
                 }
               })

I am running above method in a LWC component. File downloaded is corrupted. I think mistake I am making is somehow how I am converting body to blob but I am not able to figure it out. I also tried getting body of attachment using stream

var stream = conn.sobject('Attachment').record(res.records[0].Id).blob('Body');
                    var result = [];
                    stream.on('data', function(chunk) {
                        result.push(chunk);
                        console.log(chunk);
                    });

                    stream.on('end', function () {

                    });

But Stream.on( events is not getting fired. Sometime 'data' event fires but end event don't fire ever.

2
  • 1
    trying this. window.URL is showing as undefined for me,, its lwc right? Dec 1, 2019 at 15:56
  • yes it is LWC only Dec 1, 2019 at 17:12

1 Answer 1

1

I think the problem lies here

new Blob(l, {type: "image/jpeg"});

Blob constructor needs first parameter as byte array where as in your example you are providing it as base64 encoded string. Now you have to convert the base64 encoded string to byte array.

I tried to update your code and after converting the base64 into byte array it seems to be working.

Here is the code which you can just run in console:

const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
  const byteCharacters = atob(b64Data);
  const byteArrays = [];

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

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

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

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

function downloadFile(){
    var l = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='  
  var blob = b64toBlob('','image/png');
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'todo-1.png';
  document.body.appendChild(a);
  a.click();
  window.URL.revokeObjectURL(url);
  console.log('Downloading file');
}


window.onload = onLoad();

Reference : https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript

8
  • HI Kiran I am not sure that whether I am getting a string or a blob from response. Above code doesn't work for body I am getting from response. atob method is failing with error "the string to be decoded contains character outside of latin 1 range" Dec 1, 2019 at 13:56
  • You will get string in base64 format. Dec 1, 2019 at 22:09
  • Give it a try, update your code considering you are getting base64 and see how this works. Dec 1, 2019 at 22:10
  • Yes I gave it a try .. it is not working Dec 2, 2019 at 7:48
  • 1
    Let me reproduce this end to end..my general assumption was Salesforce uses base64 in APIs for binary data so that data stays intact. Dec 3, 2019 at 18:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .