Downloading files to local storage rather than keeping them in cloud storage has several advantages. These include easier access, access without an internet connection, and complete ownership of your data.

You can download single and multiple files using built-in Node.js modules. You can also use a third-party library instead, to achieve the same results.

Downloading Files Without a Third-Party Library

To download a file using Node.js, without the aid of third-party packages, you’ll need three core Node.js modules: fs, https, and path.

The fs module supports many file tasks including read, create, update, remove, and rename. The https module creates a web server to handle requests and deliver responses. The path module provides a way to interact with directory and file paths.

Using these modules, you can send an HTTP GET request to access a file resource from a web server and then make a copy of the resource in your local system.

To begin, import the required modules:

        const https = require('https');
const fs = require('fs');
const path = require('path');

You will need to use the filename from the URL as a good default name to save it. You can use the path module’s .basename() method to obtain a file's name from its URL. This method takes a path argument and returns the last portion of a path.

For example:

        const filename = path.basename(url);

Then, request the file from the server by invoking the https.get() method. This method takes the URL as the first argument and a callback function for the response as the second argument

Pass the url variable as the first argument and then a callback function for processing when this method receives a response stream:

        https.get(url, (res) => {
})

In the callback function, you can use the fs.createWriteStream() method to create a new writable stream, passing the filename variable as an argument.

For example:

        const fileStream = fs.createWriteStream(filename);
res.pipe(fileStream);

The createWriteStream() method eases the process of writing data to a file, especially when you’re handling large chunks of data.

The pipe() method then sends the GET response data stream to the fileStream object.

To log a message to the console after the script has finished downloading the file, attach a .on() event emitter to the fileStream variable:

        fileStream.on('finish', () => {
  fileStream.close();
  console.log('Download finished');
});

The fileStream object emits a finish event when it has written all the data to the file. Catch this via the .on() method and provide a callback function to close the fileStream and log a message to the console.

For better execution and efficient script reusability, wrap this code in a function that takes the URL as its argument:

        function downloadFile(url) {
    const filename = path.basename(url);

    https.get(url, (res) => {
        const fileStream = fs.createWriteStream(filename);
        res.pipe(fileStream);

        fileStream.on('finish', () => {
            fileStream.close();
            console.log('Download finished')
        });
    })
}

To run the function, call it and pass the URL of the file you want to download:

        downloadFile([file url]);

To run the script, open your terminal and enter node followed by the name of the JavaScript file:

        node [script name]

This script will download the file URL you passed to the downloadFile() function and save it in your working directory.

Handling Errors When Downloading Files

In Node.js, specific errors like writing to the stream, poor service connection, or issues with the file itself could occur when downloading files. It's crucial to log error messages when these errors take place to be able to tackle the issue.

Try/Catch Block

A try-catch block is a programming structure that enables you to handle potential errors and exceptions in your code.

The try-and-catch blocks make up the try...catch block. The try block's code runs first, and the catch block's code runs if the try block throws an exception.

        try {
    downloadFile([file url]);
} catch (error) {
    console.log(error);
}

Use a try/catch block to ensure that you can catch any download-related errors. You can then handle any error as necessary, such as logging it to the console or retrying the download.

HTTP Response Status Code

Status codes for HTTP responses show whether a particular HTTP request has been successfully carried out.

For example:

        https.get(url, (res) => {
    const code = res.statusCode();
    console.log(code)
    const fileStream = fs.createWriteStream(filename);
});

If the request returns a status code outside the success range, 200-299, there was a problem with the request. Check the HTTP status code, then look up the meaning of the status code to deal with the error as necessary.

Downloading Multiple Files

You can download multiple files simultaneously by passing the file URLs as arguments when running node [script name]. To perform this task, you must modify certain parts of your script.

In JavaScript, arguments passed alongside the node command are available in process.argv, a property of the global Node.js object. This property returns an array of the command line arguments. The first element in this array should be node, the actual command that you run. The second will be the script filename, then each following argument should be a URL.

To download multiple files all at once, save the array from process.argv in a variable. Then run the slice() method to remove the first two elements, that aren’t URLs:

        const args = process.argv;
const urls = args.slice(2);

The slice() method creates a new array from selected elements in an array. This method selects from a specified start to a specified (non-inclusive) end.

In this case, passing a value of 2 removes the node command name and your script filename.

Finally, using JavaScript’s map method, pass each element in the urls array to downloadFile():

        urls.map(url =>{
    downloadFile(url)
});

To run the code, enter the node command along with the name of your JavaScript file and the URLs you want to download:

        node [script name] url1 url2 url3 

Using a Third Party Library

You can also download files using a third-party library like the npm download package.

Inside your script directory, run the following npm command to install the download package:

        npm install download

Require the downloaded package in your script, then save the command-line arguments in an array:

        const download = require('download');
const args = process.argv;
const urls = args.slice(2);

You can now use the download library to download files. You can do this in several ways depending on your particular objective.

For example:

        async function downloadFile(urls){
await Promise.all(urls.map((url) => download(url, "files")))
};

downloadFile(urls);

Declare the downloadFile function as async, and create a Promise to wait until the particular task is complete with the await keyword. Map the urls array to the download function and pass the name of a local folder—"files", in this case—to store the files in.

Downloading Files to the Local File System

Node’s built-in functions, like fs and https, make it easy to write a file downloader. To make it even easier, you can use a third-party module like download.

Both methods let you download files from a remote server and save them to the local file system. You should choose the best method for your needs and use it in your next Node.js application.