Explain Codes LogoExplain Codes Logo

Detect when a browser receives a file download

javascript
prompt-engineering
best-practices
performance
Anton ShumikhinbyAnton Shumikhin·Feb 4, 2025
TLDR

Track a server-set cookie to detect a file download. Initialize an interval check using JavaScript. As soon as the cookie appears, it means the download has started. At this point, clear the interval and execute any logic that should run post-download.

let checkDownload = setInterval(() => { if (document.cookie.includes('download_token=12345')) { clearInterval(checkDownload); // Download has arrived like an ordered pizza! alert('File is being downloaded.'); document.cookie = 'download_token=; Max-Age=-99999999;'; // Expire the cookie, nobody likes cookie crumbs! } }, 1000); // Check every 1 second

Use a unique identifier in the cookie to handle concurrent downloads like a juggling pro 🤹‍♂️!

Additional strategies

Pop-up alert with window.onblur()

Enhance your file download detection with window.onblur(). It allows you to detect when a browser dialog surfaces, which might be due to a file download:

window.onblur = function() { if (document.cookie.includes('download_token=12345')) { // It's as if a new episode of your favorite series is out! // Time to dim the lights and bring in the popcorn } };

Security on point!

Improve security by using httpOnly and Secure flags when setting the cookie:

setcookie("download_token", "12345", 0, "/", "", true, true); // Like attaching a lock to the cookie jar!

Embrace the stream

Consider streaming data when dealing with larger files:

fetch('file/stream/url') .then(response => response.body.pipeTo(new WritableStream(/* ... */))) .then(() => console.log('Download complete!')); // Look, Mum! I'm streaming!

Advanced approaches and edge cases

Multiple downloads? No problem!

Use a mapping between downloads and tokens to manage several downloads simultaneously:

let downloads = { token1: { status: 'initializing' }, token2: { status: 'downloading' }, // Challenge accepted! Multiple downloads under control }; // Check respective token status

Timeout and weaker references

Incorporate a timeout to remove the interval check if download completion isn't detected within a pre-set duration:

setTimeout(() => clearInterval(checkDownload), 10000); // 10-second countdown activated, it's an escape room situation!

Prevent memory leaks; clean up is essential!

window.onfocus = () => clearInterval(checkDownload); // Like taking out the garbage after a party!

Other monitoring methods

AJAX pooling

Fetch status updates by polling the server via AJAX:

function checkDownloadStatus(token) { // AJAX request to server to check the status: "Hey server, what's cooking?" }

iframes

Initiate download within an iframe and monitor its loading state:

let downloadIframe = document.createElement('iframe'); downloadIframe.style.display = 'none'; downloadIframe.src = 'download/url/with/token'; document.body.appendChild(downloadIframe); // Playing hide-n-seek with an iframe!

UX matters!

Inform the user about the progress of the download:

// Show user a loading spinner, because who doesn't like spinning things? document.getElementById('loading').style.display = 'block'; // Hide spinner when download starts, it's showtime! document.cookie = 'downloaded=; Max-Age=-99999999;'; document.getElementById('loading').style.display = 'none';