Chrome Extension Downloads Management — Best Practices

5 min read

Downloads Management Patterns

This guide covers patterns for managing downloads in Chrome extensions using the Downloads API.

Starting Downloads

Use chrome.downloads.download() to initiate downloads:

async function startDownload(url, filename) {
  const downloadId = await chrome.downloads.download({
    url: url,
    filename: filename,
    saveAs: true,
    method: 'GET'
  });
  return downloadId;
}

Options:

Monitoring Progress

Listen to chrome.downloads.onChanged to track download progress:

chrome.downloads.onChanged.addListener((downloadDelta) => {
  if (downloadDelta.state) {
    console.log(`State: ${downloadDelta.state.current}`);
  }
  if (downloadDelta.bytesReceived) {
    const progress = (downloadDelta.bytesReceived / downloadDelta.totalBytes) * 100;
    updateProgressBar(downloadDelta.id, progress);
  }
});

Download States

Downloads transition through these states:

Progress UI in Popup

Display download progress in your extension popup:

function updateProgressBar(downloadId, percent) {
  const progressBar = document.getElementById('download-progress');
  progressBar.style.width = `${percent}%`;
  progressBar.textContent = `${Math.round(percent)}%`;
}

Filename Generation

Generate dynamic filenames with timestamps:

function generateFilename(baseName, extension) {
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const sanitized = baseName.replace(/[^a-z0-9]/gi, '_').toLowerCase();
  return `${sanitized}_${timestamp}.${extension}`;
}

File Type Handling

Set appropriate MIME types and extensions:

const fileTypes = {
  json: { mime: 'application/json', ext: 'json' },
  csv: { mime: 'text/csv', ext: 'csv' },
  png: { mime: 'image/png', ext: 'png' }
};

Batch Downloads

Queue multiple downloads with concurrency control:

async function batchDownload(urls, concurrency = 3) {
  const queue = [...urls];
  const active = [];
  
  while (queue.length > 0 || active.length > 0) {
    while (active.length < concurrency && queue.length > 0) {
      const url = queue.shift();
      const promise = chrome.downloads.download({ url }).then(id => {
        active.splice(active.indexOf(promise), 1);
      });
      active.push(promise);
    }
    await Promise.race(active);
  }
}

Download from Generated Data

Create downloads from Blob URLs for generated content:

async function downloadDataAsFile(data, filename, mimeType) {
  const blob = new Blob([data], { type: mimeType });
  const url = URL.createObjectURL(blob);
  await chrome.downloads.download({ url, filename });
  URL.revokeObjectURL(url);
}

Cancel, Pause, Resume

chrome.downloads.cancel(downloadId);    // Cancel download
chrome.downloads.pause(downloadId);    // Pause download
chrome.downloads.resume(downloadId);   // Resume paused download

Open and Show Files

chrome.downloads.open(downloadId);    // Open downloaded file
chrome.downloads.show(downloadId);    // Show in file manager

Download History

Query past downloads:

async function getDownloadHistory() {
  const downloads = await chrome.downloads.search({ limit: 50 });
  return downloads.filter(d => d.state === 'complete');
}

Shelf Control

Control the download shelf (bottom bar):

chrome.downloads.setShelfEnabled(false);  // Hide download shelf
chrome.downloads.setShelfEnabled(true);   // Show download shelf

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.