I have a webapp that needs to allow the user to download files programmatically.
I know chrome blocks multi-file downloads, that is why drive and dropbox zip files when you select more than one to download in bulk.
My problem is that Chrome is blocking the programmatic download even when the user clicks the download button for each file individually. Usually, the first file goes through but from the second interaction the download is blocked.
I know there must be a way around it because drive and dropbox do it, so what am I missing?
Here’s the hook I created to do programmatic download:
import JSZip from 'jszip';
import { type TransferredFile } from '../../features/fileTransfer/fileTransfer.type';
import { useState } from 'react';
type FileTransferDownload = {
download: () => Promise<void>;
isDownloadComplete: boolean;
};
const programmaticDownload = (blob: Blob, filename: string): void => {
const href = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.target = '_blank';
link.href = href;
link.id = Math.random().toString();
link.download = filename;
link.click();
window.URL.revokeObjectURL(href);
};
export const useFileTransferDownload = (
receivedFiles: TransferredFile[],
): FileTransferDownload => {
const [isDownloadComplete, setDownloadComplete] = useState<boolean>(false);
const downloadFileUnzipped = async (file: TransferredFile): Promise<void> => {
const { name, downloadUrl } = file;
try {
const response = await fetch(downloadUrl);
const blob = await response.blob();
programmaticDownload(blob, name);
setDownloadComplete(true);
} catch (error) {
console.error('Download failed:', error);
setDownloadComplete(false);
}
};
return {
download: downloadFileUnzipped,
isDownloadComplete,
};
};