Reputation: 19
My goal is to have a script that downloads all files inside the given array:
var links = ['http://file-examples.com/wp-content/uploads/2017/10/file_example_JPG_100kB.jpg',
'http://file-examples.com/wp-content/uploads/2017/10/file_example_TIFF_1MB.tiff'];
function downloadAll(urls) {
var link = document.createElement('a');
link.setAttribute('download', null);
link.style.display = 'none';
document.body.appendChild(link);
for (var i = 0; i < urls.length; i++) {
link.setAttribute('href', urls[i]);
link.click();
}
document.body.removeChild(link);
}
downloadAll(window.links)
This was working smoothly until (I believe) the latest chrome updates.
I've been gathering info around but it seems there's no fix available yet.
Can someone gimme a help here please? Basically want to have a multiple file download script working in JS.
Thanks in advance for the help!
Upvotes: 1
Views: 3022
Reputation: 667
Using File System Access API, we can archive the same goal.
async function DownloadFiles(paramToFiles) {
try {
var dirHandle = await window.showDirectoryPicker({
startIn: 'videos',//default folder
mode: 'readwrite'//ask for write permission
});//move script from function startDownload to here, because of an error "SecurityError: Failed to execute 'showDirectoryPicker' on 'Window': Must be handling a user gesture to show a file picker.". It was working on localhost.
for (var index in paramToFiles.Files) {
var file = paramToFiles.Files[index];
const fileHandle = await dirHandle.getFileHandle(file.FileName, { create: true });
if (await verifyPermission(fileHandle, true)) {
const writable = await fileHandle.createWritable();
await writable.write(await getBlob(file.URL));
await writable.close();
}
}
}
catch (error) {
alert(error);
}
return false;
}
async function startDownload(dirHandle, paramToFiles) {
//move above
}
async function verifyPermission(fileHandle, readWrite) {
const options = {};
if (readWrite) {
options.mode = 'readwrite';
}
if ((await fileHandle.queryPermission(options)) === 'granted') {
return true;
}
if ((await fileHandle.requestPermission(options)) === 'granted') {
return true;
}
return false;
}
function getBlob(urlToGet) {
const blob = fetch(urlToGet).then(data => data.blob());
return blob;
}
You can call it like this.
<script>
function doDownload() {
DownloadFiles({
'Files': [
{
'FileName': 'Download-Nih-01.zip',
'URL': '/Download/Download-Nih-01.zip'
},
{
'FileName': 'Download-Nih-02.zip',
'URL': '/Download/Download-Nih-02.zip'
},
{
'FileName': 'Download-Nih-03.zip',
'URL': '/Download/Download-Nih-03.zip'
}
]
});
}
const butDow = document.getElementById('doDownload');
butDow.addEventListener('click', async () => doDownload())
</script>
A few things to note about this implementation:
This was button declaration that I used to test this.
<button type="button" id="doDownload">Download</button>
As of this writing (18-Aug-2021), this API is supported by chrome, edge and opera. I've tested it using ms edge (chromium) and its working.
ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker
Upvotes: 2