lowcrawler
lowcrawler

Reputation: 7599

How to save binary image from http request in node

With nodejs, I am using the following code to connect to a camera via digest auth and download the image data.

var request = require('request')

var options = {
    'url': uri,
    'auth': {
        'user': user,
        'pass': pass,
        'sendImmediately': false
    }
};

var request = request.get(options, function (error, response, body) {
    if (!error && response.statusCode == 200) {

        console.log('response :>> ', response);
        const filename = "picture.jpg"
        // const fileContents = Buffer.from(resp.body._readableState.buffer.head, 'base64')
        const fileContents = Buffer.from(body)
        // fs.writeFile(filename, fileContents, (err) => {
        fs.writeFileSync(filename, fileContents, (err) => {
            if (err) return console.error(err)
            console.log('file saved to ', filename)
            return body
        })
    }
    else {
        console.log('Code : ' + response.statusCode)
        console.log('error : ' + error)
        console.log('body : ' + body)
    }
});

This creates a ~360kb file or so -- roughly 2x the expected size of the image when downloaded via a browser. It also does not open in an image editing software or anything -- it's not creating a valid jpg.

When writing the body to the console, it looks like a bunch of this: Console output

I'm unsure how to turn this data into an image file that I can write to the filesystem. Help?

Update: I have changed the buffer.from to try 'binary', 'utf-8', 'utf8', 'base64url' and 'base64'... to no avail.

The response does come back with a content type of 'image/jpeg; charset="UTF-8"' but the created file is still invalid.

Update #2: This question: nodejs convert image between buffer and string taught me that once a jpg gets sent to UTF8, you can't go back to a valid jpg.... so then I started wondering if I could request in a different encoding. Turns out, Request allows an optional encoding parameter. (sad to see it's deprecated needlessly... but with 20 million a week downloading it, I don't think it's going anywhere)

So changing my options to:

var options = {
    'url': uri,
    'encoding': 'binary',
    'auth': {
        'user': user,
        'pass': pass,
        'sendImmediately': false
    }
};

and my buffer creation to this: const fileContents = Buffer.from(body, 'binary')

matched everything up.

Upvotes: 5

Views: 3454

Answers (1)

Mayank Goyal
Mayank Goyal

Reputation: 11

Hell of a coaster ride. Thanks, Man. @lowcrawler

I had to save the REST API response into a vRO package file using nodejs, which I just couldn't right, making me scratch my head badly. But after reading your comment and hit and trail, I made it finally. Thanks again.

var request = require('request');
var fs = require('fs');
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
var options = {
  'method': 'GET',
  'encoding': 'binary',
  'url': 'https://vro_fqdn/vco/api/packages/gitlab_vro_credential_store_confs?exportConfigurationAttributeValues=true&exportGlobalTags=true&exportVersionHistory=true&exportConfigSecureStringAttributeValues=false&allowedOperations=vef&exportExtensionData=false',
  'headers': {
    'Accept': 'application/zip',
    'Authorization': 'Basic eDIxMzxxxxxxxxxxxx5sb2NhbDpBdWcjMjAyMw=='
  }
};
request(options, function (error, response, body) {
  if (error) throw new Error(error);
  console.log(response.body);
  fs.writeFile("packageName.package",  Buffer.from(body, 'binary'), function(err){
    if (err) throw err;
    console.log("success");
    });
});

Upvotes: 1

Related Questions