diff --git a/src/Shared/Hooks/UseDownload/UseDownload.tsx b/src/Shared/Hooks/UseDownload/UseDownload.tsx index b63ccf70c..7f74a26f6 100644 --- a/src/Shared/Hooks/UseDownload/UseDownload.tsx +++ b/src/Shared/Hooks/UseDownload/UseDownload.tsx @@ -25,13 +25,36 @@ import { HandleDownloadProps } from './types' const useDownload = () => { const [isDownloading, setIsDownloading] = useState(false) + const [progress, setProgress] = useState(null) + + const getChunksDataFromResponse = async (response: Response) => { + const contentLength = +response.headers.get('Content-Length') + if (!contentLength) { + throw new Error('Invalid content length') + } + const reader = response.body.getReader() + const chunks = [] + let receivedLength = 0 + + // eslint-disable-next-line no-constant-condition + while (true) { + // eslint-disable-next-line no-await-in-loop + const { done, value } = await reader.read() + if (done) break + + chunks.push(value) + receivedLength += value.length + setProgress(receivedLength / contentLength) + } + } /** * @param downloadUrl - API url for downloading file - * @param filterType - Show toast 'Preparing file for download' + * @param showFilePreparingToast - Show toast 'Preparing file for download' * @param fileName - fileName of the downloaded file * @param showSuccessfulToast - show toast on successful download * @param downloadSuccessToastContent - Content to show in toast on successful download + * @param showProgress - show download progress, default false, returns null if false, else returns percentage downloaded */ const handleDownload = async ({ downloadUrl, @@ -39,6 +62,7 @@ const useDownload = () => { fileName, showSuccessfulToast = true, downloadSuccessToastContent = 'Downloaded Successfully', + showProgress = false, }: HandleDownloadProps): Promise => { setIsDownloading(true) try { @@ -51,10 +75,13 @@ const useDownload = () => { description: 'File will be downloaded when it is available.', }) } - const data = await (response as any).blob() + + const data = showProgress ? getChunksDataFromResponse(response) : await (response as any).blob() + + const blob = showProgress ? new Blob(data) : data // Create a new URL object - const blobUrl = URL.createObjectURL(data) + const blobUrl = URL.createObjectURL(blob) // Create a link element const a = document.createElement('a') @@ -95,7 +122,8 @@ const useDownload = () => { return null } - return { handleDownload, isDownloading } + // progress will be null if showProgress is false + return { handleDownload, isDownloading, progress } } export default useDownload diff --git a/src/Shared/Hooks/UseDownload/types.tsx b/src/Shared/Hooks/UseDownload/types.tsx index 5353c4630..c631ccbe9 100644 --- a/src/Shared/Hooks/UseDownload/types.tsx +++ b/src/Shared/Hooks/UseDownload/types.tsx @@ -20,4 +20,5 @@ export interface HandleDownloadProps { fileName?: string showSuccessfulToast?: boolean downloadSuccessToastContent?: string + showProgress?: boolean }