2

I am trying to download a JPG file stored as an attachment in Salesforce, to the local machine. I have a URL that works correctly when using a GET request in Workbench. When I try to do the same in Node.JS (using JSForce), I can't get the file to output as a JPG.

This is what I have:

var jsforce = require('jsforce');
var conn = new jsforce.Connection();
conn.login('<username>', '<password>', function(err, res) {
  if (err) { return console.error(err); }  
conn.request('https://<my-dev-ed-instance>.my.salesforce.com/services/data/v42.0/sobjects/ContentVersion/<uuid>/VersionData', function(err, res) {
 if (err) { return console.error(err); }
 console.log(res);
 fs.writeFileSync('2.jpg',res,'base64');
});
});

I believe the GET request should be returning a BASE64 string, but I cannot seem to convert it or make it useful.

Any help would be greatly appreciated!

EDIT: I found a solution. Tbh, I really just needed some sleep and to wake up and use Postman to troubleshoot properly.

var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
  'method': 'GET',
  'hostname': '<HOSTNAME>',
  'path': '/services/data/v49.0/sobjects/ContentVersion/<UUID>/VersionData',
  'headers': {
    'Authorization': 'Bearer <TOKEN>',
    'Cookie': 'BrowserId=<COOKIE>',
    'Content-Type': 'text/plain'
  },
  'maxRedirects': 20
};

var req = https.request(options, function (res) {
  var chunks = [];

  res.on("data", function (chunk) {
    chunks.push(chunk);
  });

  res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    fs.writeFileSync('output.jpg',body,'binary');
  });

  res.on("error", function (error) {
    console.error(error);
  });
});

req.end();

Thank you to those who helped, you definitely pointed me in the right direction.

1

Here is a sample JS fetch request I converted in Postman (this is pseudocode and probably wont work). I use the the following endpoint /services/data/v48.0/sobjects/Attachment/<ATTACHMENT_FILE_ID>/Body BUT the response is binary so you would need to handle that response and convert it to JPG

https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_blob_retrieve.htm

You can also try getting file content with Connect API and the following endpoint (still binary response): /services/data/v{{version}}/connect/files/<FILE_ID>/content OR create a public file sharing link with the following endpoint and use that link one way or another (PUT request): /services/data/v{{version}}/connect/files/<FILE_ID>/file-shares/link

https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_files_content.htm

https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_files_shares_link.htm

var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer <ACCESS_TOKEN>");

var requestOptions = {
  method: 'GET',
  headers: myHeaders,
  redirect: 'follow'
};

fetch("https://domain.my.salesforce.com/services/data/v48.0/sobjects/Attachment/<ATTACHMENT_FILE_ID>/Body", requestOptions)
  .then(...)
| improve this answer | |
0

The Blob Retrieve endpoint actually returns the file contents as a binary file. There's no need to base64 decode the value. See the documentation.

Attachment body content is returned in binary form. Note that the response content type will not be JSON or XML since the returned data is binary.

Note: this is for an Attachment Body, but also applies to any other Blob content.


Here's a quick example I wrote up:

var jsforce = require('jsforce');
var fs = require('fs');
const conn = new jsforce.Connection();

conn.login('<username>', '<password>')
    .then(() => {
        conn.request('/services/data/v49.0/sobjects/ContentVersion/.../VersionData').then((result) => {
            fs.writeFileSync('output.data', result);
        });
    });
| improve this answer | |
  • Unfortunately, I'm having trouble working out how to implement that in Node.JS, where I don't have access to cURL. Any ideas? – Scott Harrison Aug 23 at 10:29
  • @ScottHarrison I wrote up an example that runs on my computer. Give this a try and let me know. – sfdcfox Aug 23 at 10:56
  • Thank you for following up. Unfortunately, no go. It should be downloading a 130KB JPG file, so I changed output.data to output.jpg. What it downloads is a 235KB JPG that is unreadable. – Scott Harrison Aug 23 at 11:14
  • @ScottHarrison Sounds like you've got the wrong file. Even if it were base64 encoded, a 235kb base64 file would be about 176kb, not 130kb. Try opening the file in a hex editor or IDE, see what the contents looks like. It should start hex codes 'FF D8 FF' followed shortly by the text characters 'JFIF'. If not, you might have the wrong file. – sfdcfox Aug 23 at 11:29
  • I'm pretty certain it's the right file - when I enter that URL in to Workbench, it downloads the JPG correctly. I stuck the output.data in to a hex editor and it does show JFIF at the beginning, without the 'FF D8 FF' though. – Scott Harrison Aug 23 at 11:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.