Build api to download file without exposing download URL [Express, Node]

don't want to expose download URL or want to generate dynamic download url?

It is fairly easy with Express / Node.

new

 

Steps:

1. create express server

install command : npm install express axios

const express = require('express');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3000;

/*
 endpoints goes here
*/

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

2. create endpoint

  1. From External URL
app.get('/download', async (req, res) => {
    try {
        // URL of the file to download
        const fileUrl = 'URL_OF_YOUR_FILE_HERE';

        // Fetch the file from the URL
        const response = await axios.get(fileUrl, { responseType: 'stream' });

        // Set content disposition header to force download
        res.setHeader('Content-Disposition', 'attachment; filename="downloaded_file.txt"');
        
        // Pipe the file stream to the response
        response.data.pipe(res);
    } catch (error) {
        console.error('Error downloading file:', error);
        res.status(500).send('Error downloading file');
    }
});

   2. From same server

app.get('/download/:fileName', (req, res) => {
    const fileName = req.params.fileName;
     //or
     const fileName = "filename here"; 
    const filePath = path.join(__dirname, 'files', fileName); // Adjust the path to your files directory

    // Check if the file exists
    if (fs.existsSync(filePath)) {
        // Set content disposition header to force download
        res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
        
        // Stream the file to the response
        const fileStream = fs.createReadStream(filePath);
        fileStream.pipe(res);
    } else {
        res.status(404).send('File not found');
    }
});

complete code

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

const app = express();
const PORT = process.env.PORT || 3000;

// Define the route to handle file downloads
app.get('/download/:fileName', (req, res) => {
    const fileName = req.params.fileName;
    const filePath = path.join(__dirname, 'files', fileName); // Adjust the path to your files directory

    // Check if the file exists
    if (fs.existsSync(filePath)) {
        // Set content disposition header to force download
        res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
        
        // Stream the file to the response
        const fileStream = fs.createReadStream(filePath);
        fileStream.pipe(res);
    } else {
        res.status(404).send('File not found');
    }
});

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});