68

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!

9 Answers 9

66

Use the axios:

const response = await axios.get(url,  { responseType: 'arraybuffer' })
const buffer = Buffer.from(response.data, "utf-8")
Sign up to request clarification or add additional context in comments.

5 Comments

This should be the accepted answer in 2021
And also in 2022.
why "utf-8"? that is a binary content
bless your soul
Thank you. I need to load image from url into buffer to check it's metadata with image-meta and this works really well.
64

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.

5 Comments

thanks that worked! Do I need to be concerned about loading too many images this way, or are they automatically deleted?
The V8 Javascript engine will garbage collect unused memory, so you should be fine.
You mention it will "output" a buffer. Could you describe where the output is? request does not return a value.
@TamusJRoyce Here's a more complete example: stackoverflow.com/a/17133012/1935918
Request is deprecated, there are others: github.com/request/request/issues/3142
38
import fetch from "node-fetch";

let fimg = await fetch(image.src)
let fimgb = Buffer.from(await fimg.arrayBuffer())

1 Comment

worked for me, even with native node fetch nodejs.org/dist/latest-v20.x/docs/api/globals.html#fetch, but still marked as experimental 👍
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

2 Comments

uri is missing: request({ uri: url, encoding: null }, (err, resp, buffer) => {
10

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.

Comments

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.

2 Comments

i tried using the request method, but the buffer is always null. If i put in the imageurl directly in the browser it loads fine. Any idea why that may be the case?
Sorry, I had the wrong signature for the callback. I've updated the answer.
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");
}

Comments

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);
    }
})();

Comments

1

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();

Comments

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.