0

Before I start with the question, I have gone through multiple stackoverflow answers around similar sort of questions (including those which have been asked and not answered till now). I have also gone through one of the medium articles. So, I have done a fair bit of research.

I have been trying to download multiple files using presigned urls. The code below was working few days back (this might sound familiar ;)) but currently, I am just able to download one file that too the download is random. Sometimes the first file is downloaded and sometimes the last. Code is provided below:

downloadItem() { let urls = []; for(let item of this.selectedRowsData) { //calling the service to fetch the presigned url this.dataService.getPresignedToDownloadAll( item.value, item.id).subscribe((res) => { urls.push(res); this.download(urls); /**if(urls.length === selectedRowData.length) { this.download(urls); }**/ //have tried this code too where I just invoke download only once when I have all the presigned urls }); } } download(urls: any) { var self = this; var url = urls.pop(); setTimeout(function(){ self.snackBarService.loadComponent({ isSuccess: true, message: MESSAGES.downloadInProgress, }); var a = document.createElement('a'); a.setAttribute('href', url); document.body.appendChild(a); a.setAttribute('download', ''); a.setAttribute('target', '_self'); a.click(); // a.remove(); }, 1000) } 

Any help is much appreciated.

2 Answers 2

1

I was not able to download the multiple images from presigned urls on the same browser tab which is what I was trying to do with a.setAttribute('target', '_self');

But I was able to make it work by setting target as _blank which does open up a new tab but closes those opened tabs once the download is done. Though this is not a great user experience but as of now we have gone ahead with this implementation. This is what the final code looks like

downloadItem() { let urls = []; for(let item of this.selectedRowsData) { //calling the service to fetch the presigned url this.dataService.getPresignedToDownloadAll( item.value, item.id).subscribe((res) => { urls.push(res); this.download(urls); }); } } download(urls: any) { var self = this; var url = urls.pop(); setTimeout(function(){ self.snackBarService.loadComponent({ isSuccess: true, message: MESSAGES.downloadInProgress, }); var a = document.createElement('a'); a.setAttribute('href', url); a.setAttribute('download', ''); a.setAttribute('target', '_blank'); document.body.appendChild(a); a.click(); // a.remove(); }, 1000) } 
Sign up to request clarification or add additional context in comments.

Comments

0

For anybody in the future. You can do it all in 1 tab with blob. Code here:

 const blobs = await Promise.all(presignedUrls.map(async (presignedUrl) => { const response = await fetch(presignedUrl); const blob = await response.blob(); return blob; })); blobs.forEach((blob, i) => { setTimeout(() => { const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = filesNames[i]; link.click(); // we need this because of Chrome blocking over 10 files download }, i * 200); }); } 

1 Comment

This is impractical for large objects as the blob is stored in memory.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.