Explain Codes LogoExplain Codes Logo

How to download a file with Node.js (without using third-party libraries)?

javascript
promises
callbacks
best-practices
Anton ShumikhinbyAnton ShumikhinΒ·Feb 17, 2025
⚑TLDR

To download a file in Node.js without third-party libraries, use the http or https module based on the URL's protocol. Make a http.get() or https.get() call, and pipe the response to fs.createWriteStream. Here's an example for an HTTPS URL:

const https = require('https'); const fs = require('fs'); // Please replace with real URL and File path. const url = "https://example.com/file.ext"; const filePath = "local_file.ext"; https.get(url, response => { const fileStream = fs.createWriteStream(filePath); response.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(); // Like closing the refrigerator door. πŸ˜„ console.log('File downloaded!'); }); });

Code breakdown and best practices

When downloading files using Node.js, it’s vital to consider the protocol being used. Whether the URL starts with http:// or https://, pick the appropriate Node.js module.

Invoke http.get or https.get to initiate a GET request. This function provides a stream, which we can pipe directly to a writable stream created by fs.createWriteStream. This method efficiently writes the incoming data to the file system.

const http = require('http'); const fs = require('fs'); // true URL and File path needed. const url = "http://example.com/file.txt"; const savePath = "./local_dir/local_file.txt"; const file = fs.createWriteStream(savePath); // Our empty box waiting for parcel. 😜 const request = http.get(url, response => { response.pipe(file); file.on('finish', () => { file.close(() => console.log('Download complete. Enjoy your parcel. 😊')); }); });

Error handling and validation are boxes that cannot remain unchecked. Always confirm a HTTP 200 status code to make sure the download request was successful. Set up error listeners for both the request and file stream to catch network and file system issues.

request.on('response', (response) => { if (response.statusCode !== 200) { console.error(`Oops, server responded with ${response.statusCode}, not what we expected.`); request.abort(); // No parcel? Abort mission! πŸš€ } }); file.on('error', (err) => { fs.unlink(savePath, () => {}); // Delete the file async if the download wasn't successful throw err; });

Considerations for a robust execution

To make your download more robust, make sure to handle edge cases. Run through the following checklist:

  • Network errors: May happen due to connectivity problems or request errors.
  • File system permissions: Authorization issues on the output directory may prevent writing the file.
  • Server Response: If the server's response isn't as expected (not receiving a 200 status code), abort the request.
  • Partial Download: Ensure to delete the partially downloaded file if an error occurs to avoid corrupt files.
  • Race Conditions: Be careful when other parts of your application are trying to access this file.

Downloading files from user input

For accepting input via the command line or making this operation part of a larger application's flow, wrap the download logic within a function and call it whenever needed.

const http = require('http'); const fs = require('fs'); const process = require('process'); function downloadFile(url, outputLocationPath) { const file = fs.createWriteStream(outputLocationPath); // Get the box ready! πŸ“¦ http.get(url, (response) => { // Check server response if (response.statusCode !== 200) { console.error(`Yikes! Server responded with ${response.statusCode}`); return; } response.pipe(file); // On successful response, pipe the data to file }); file.on('finish', () => file.close(() => console.log(`Package delivered to ${outputLocationPath}`))); file.on('error', (err) => { fs.unlink(outputLocationPath); // No parcel? No problem. We remove the box! console.error(err.message); }); } const url = process.argv[2]; // The URL to download from const outputPath = process.argv[3]; // The destination path downloadFile(url, outputPath); // we call DHL transfer! 🚚