61

I am new to nodejs and am trying to set up a server where i get the exif information from an image. My images are on S3 so I want to be able to just pass in the s3 url as a parameter and grab the image from it.

I am u using the ExifImage project below to get the exif info and according to their documentation:

"Instead of providing a filename of an image in your filesystem you can also pass a Buffer to ExifImage."

How can I load an image to the buffer in node from a url so I can pass it to the ExifImage function

ExifImage Project: https://github.com/gomfunkel/node-exif

Thanks for your help!

CodeMonkeyB
  • 2,970
  • 4
  • 22
  • 29

9 Answers9

63

Try setting up request like this:

var request = require('request').defaults({ encoding: null });
request.get(s3Url, function (err, res, body) {
      //process exif here
});

Setting encoding to null will cause request to output a buffer instead of a string.

Koen.
  • 25,449
  • 7
  • 83
  • 78
Dan Kohn
  • 33,811
  • 9
  • 84
  • 100
59

Use the axios:

const response = await axios.get(url,  { responseType: 'arraybuffer' })
const buffer = Buffer.from(response.data, "utf-8")
atulmy
  • 1,364
  • 15
  • 23
Depp Wang
  • 989
  • 7
  • 9
27
import fetch from "node-fetch";

let fimg = await fetch(image.src)
let fimgb = Buffer.from(await fimg.arrayBuffer())
Marius
  • 1,659
  • 3
  • 22
  • 31
cdroma
  • 271
  • 3
  • 3
21

I was able to solve this only after reading that encoding: null is required and providing it as an parameter to request.

This will download the image from url and produce a buffer with the image data.

Using the request library -

const request = require('request');

let url = 'http://website.com/image.png';
request({ url, encoding: null }, (err, resp, buffer) => {
     // Use the buffer
     // buffer contains the image data
     // typeof buffer === 'object'
});

Note: omitting the encoding: null will result in an unusable string and not in a buffer. Buffer.from won't work correctly too.

This was tested with Node 8

Yehonatan
  • 3,168
  • 7
  • 31
  • 39
9

Use the request library.

request('<s3imageurl>', function(err, response, buffer) {
    // Do something
});

Also, node-image-headers might be of interest to you. It sounds like it takes a stream, so it might not even have to download the full image from S3 in order to process the headers.

Updated with correct callback signature.

Timothy Strimple
  • 22,920
  • 6
  • 69
  • 76
7

Here's a solution that uses the native https library.

import { get } from "https";

function urlToBuffer(url: string): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    const data: Uint8Array[] = [];
    get(url, (res) => {
      res
        .on("data", (chunk: Uint8Array) => {
          data.push(chunk);
        })
        .on("end", () => {
          resolve(Buffer.concat(data));
        })
        .on("error", (err) => {
          reject(err);
        });
    });
  });
}

const imageUrl = "https://i.imgur.com/8k7e1Hm.png";
const imageBuffer = await urlToBuffer(imageUrl);

Feel free to delete the types if you're looking for javascript.

I prefer this approach because it doesn't rely on 3rd party libraries or the deprecated request library.

V Maharajh
  • 9,013
  • 5
  • 30
  • 31
5

you can do it that way

import axios from "axios";

function getFileContentById(
  download_url: string
): Promise < Buffer > {
  const response = await axios.get(download_url, {
    responseType: "arraybuffer",
  });
  return Buffer.from(response.data, "base64");
}
Piotr Tomasik
  • 9,074
  • 4
  • 44
  • 57
Mina Fawzy
  • 20,852
  • 17
  • 133
  • 156
4

request is deprecated and should be avoided if possible.

Good alternatives include got (only for node.js) and axios (which also support browsers).

Example of got:

npm install got

Using the async/await syntax:

const got = require('got');

const url = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png';

(async () => {
    try {
        const response = await got(url, { responseType: 'buffer' });
        const buffer = response.body;
    } catch (error) {
        console.log(error.body);
    }
})();
Edwin Liu
  • 7,413
  • 3
  • 28
  • 27
0

Simplest 2 line code to do this

In node.js there is inbuilt module called node-fetch. You can use that to download image from url and use as a buffer then you can save that buffer in any file system like s3-bucket azure etc.

import fetch from "node-fetch"

const image_url = "https://my-image-url.com";
const res = await fetch(image_url);
const resBuffer = await res.buffer();

Kanishka Sahu
  • 119
  • 2
  • 3