2024-09-30 Web Development

How to Download Images in Node.js Using Axios and fs-extra

By O Wolfson

The Node.js function described in this article is designed to download an image from a specified URL and save it to a local file path. It uses axios for making HTTP requests and fs-extra for handling file system operations.

javascript
const fs = require("fs-extra");
const path = require("node:path");
const axios = require("axios");

async function downloadImage(url, filepath) {
  const response = await axios({
    url,
    responseType: "stream",
  });
  return new Promise((resolve, reject) => {
    response.data
      .pipe(fs.createWriteStream(filepath))
      .on("finish", () => resolve())
      .on("error", (e) => reject(e));
  });
}

module.exports = downloadImage;

Step-by-Step Breakdown

  1. Importing Required Modules:

    • fs-extra: An extension of the native fs module with additional useful file system methods.
    • path: A module for handling and transforming file paths.
    • axios: A promise-based HTTP client for making requests to external servers.
  2. Defining the downloadImage Function:

    • The function is declared as async, which means it returns a promise and allows the use of await within it.
  3. Making the HTTP Request:

    • axios is used to make a GET request to the specified URL.
    • The responseType: "stream" option tells axios to treat the response data as a stream. This is crucial for handling large files like images efficiently without loading the entire file into memory.
  4. Handling the Response:

    • The function returns a new promise to manage the asynchronous file writing operation.
    • response.data is the stream containing the image data.
  5. Piping the Data Stream to a File:

    • response.data.pipe fs.createWriteStream(filepath) pipes the data stream to a writable stream created by fs.createWriteStream(filepath).
    • fs.createWriteStream(filepath) creates a writable stream to the specified file path (filepath). This stream will write the data to the file.
  6. Listening for Stream Events:

    • .on("finish", () => resolve()): This event is triggered when the writable stream has finished writing all data to the file. The promise is resolved, indicating the operation's success.
    • .on("error", (e) => reject(e)): This event is triggered if there is an error during the streaming or writing process. The promise is rejected with the error, allowing for error handling in the calling code.

Usage Example

To use this function, you would call it with a URL and a file path where you want to save the downloaded image. Here’s a quick example:

javascript
const downloadImage = require("./imageDownloader");
const path = require("node:path");

(async () => {
  const url = "https://example.com/image.jpg"; // Replace with the image URL
  const filepath = path.resolve(__dirname, "images", "image.jpg"); // Specify the save location

  try {
    await downloadImage(url, filepath);
    console.log("Image downloaded successfully.");
  } catch (error) {
    console.error("Error downloading image:", error);
  }
})();

In this example:

  1. The downloadImage function is imported from the imageDownloader.js file.
  2. The function is called with a URL and a file path, downloading the image and saving it locally.
  3. Error handling is included to log any issues that occur during the download process.