Reputation: 1105
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.
Upvotes: 0
Views: 921
Reputation: 5039
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);
});
}
Upvotes: 0
Reputation: 1105
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)
}
Upvotes: 1