Search code examples
javascriptnode.jsvideodownloadmp4

How can I download MP4 file from https link with redirect in Node.js?


Again I have a problem that I cannot solve, I am learning Node.js and there are many things that I do not know. The thing is the following, I have the following file called downloader.js

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

function downloader (url, callback) {

    const filename = path.basename (url)

    const req = https.get (url, (res) => {
        const file = fs.createWriteStream (`$ {filename} .mp4`)
        res.pipe (file)

        file.on ("error", (error) => {
            console.log (`There was an error writing the file. Details: $ {error}`)
        })

        file.on ("close", () => {
            callback (filename)
        })

        file.on ('finish', () => {
            file.close ()
            console.log ("Completely downloaded.")
        })
    })

    req.on ("error", (error) => {
        console.log (`Error downloading file. Details: $ {error}`)
    })
}

module.exports = {
    downloader
}

And I have a video, which I get the download url from a call to the Zoom api, with the following link: https://us02web.zoom.us/rec/download/06L34fQudvvSaAGYJ6Chk6RC0fuV-ebwyu9Ar_Ihrm4WRmD3xbpPAjnYfIFInOBz1PBPPAjnYPhoJlf4p3xbpPAjnYFIFIXMD3xbpPAjnYFIFIXMD3xbpPAjnYphoJlf4

When calling the downloader function, all good, I download the file in mp4 format but, the problem is that it is not the full 700MB video in mp4 format, but it is an html document in mp4 format.

Here you can see what I mean

I do not understand why the file does not download correctly. When I do it with any other type of file such as a jpeg image, it downloads it without problems, but with the mp4 format I can't get the file to download. What do you think is happening?


Solution

  • Given that the link you posted points to an Error page saying the recording does not exist, I was unable to confirm this solution works.

    However, assuming it functions similar to other recording links, when navigating to the location in a web browser, you are automatically redirected to a new uri to automatically start the download.

    Assuming this is the case, what you are actually looking for is how to follow redirects on an external API request.

    I would recommend the npm axios package, since it will automatically follow redirects.

    You can then do something like:

    const axios = require('axios');
    const fs = require('fs');
    const path = require('path');
    
    function downloader(url, callback) {
        axios({
            method: 'get',
            url: url,
            responseType: 'stream'
        })
            .then(function (response) {
                return new Promise((resolve, reject) => {
                    const filename = path.basename(url);
                    const file = fs.createWriteStream(`${filename}.mp4`);
                    response.data.pipe(file);
    
                    file.on("error", (error) => {
                        return reject(`There was an error writing the file. Details: $ {error}`);
                    });
    
                    file.on('finish', () => {
                        file.close();
                    });
    
                    file.on('close', () => {
                        return resolve(filename);
                    });
                });
            })
            .catch(function (error) {
                // handle error
                console.log(error);
            })
            .then(function (filename) {
                callback(filename);
            })
    }
    
    module.exports = {
        downloader
    };
    

    You could also directly return the axios promise and make your downloader function return a Promise instead of a function that takes a callback.

    You could also try the follow-redirects package if you were looking to keep the https variable.