Reputation: 328
I am generating an excel file on server NodeJS side, by request from the React frontend side. What can I use - some type of event or promise in order to verify if blob downloading process is finished? I need this status to set a Button element loading state while file is downloading.
React client side function:
export const download = (url, filename) => {
fetch(url, {
mode: 'no-cors'
/*
* ALTERNATIVE MODE {
mode: 'cors'
}
*
*/
}).then((transfer) => {
return transfer.blob(); // RETURN DATA TRANSFERED AS BLOB
}).then((bytes) => {
let elm = document.createElement('a'); // CREATE A LINK ELEMENT IN DOM
elm.href = URL.createObjectURL(bytes); // SET LINK ELEMENTS CONTENTS
elm.setAttribute('download', filename); // SET ELEMENT CREATED 'ATTRIBUTE' TO DOWNLOAD, FILENAME PARAM AUTOMATICALLY
elm.click(); // TRIGGER ELEMENT TO DOWNLOAD
elm.remove();
}).catch((error) => {
console.log(error); // OUTPUT ERRORS, SUCH AS CORS WHEN TESTING NON LOCALLY
})
}
I've tried:
To return a false in .then(bytes)
block, to use async, await in fetch
. Only the result I got is console.log in where .then(bytes) block gives a proper sync:
}).then((bytes) => {
console.log("Downloaded, working");
let elm = document.createElement('a'); // CREATE A LINK ELEMENT IN DOM
elm.href = URL.createObjectURL(bytes); // SET LINK ELEMENTS CONTENTS
The oher ways immideatelly sets variable (I know because of promise), so Butoon spin is not sync(1 second) with download process (3 seconds). Is there any other ways possibly?
Initial client-side request:
fetch('/api/hrreportdetailed', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(
{state}
)
});
download('/api/hrreportdetailed',"Report "+getDDMMYYY(new Date())+".xlsx");
setBtnLoad2(variable);
Upvotes: 0
Views: 1952
Reputation: 328
I remade the function and now it's working as I expected:
export const download = async (url, filename) => {
let response = await fetch(url, {
mode: 'no-cors'
/*
* ALTERNATIVE MODE {
mode: 'cors'
}
*
*/
});
try {
let data = await response.blob();
let elm = document.createElement('a'); // CREATE A LINK ELEMENT IN DOM
elm.href = URL.createObjectURL(data); // SET LINK ELEMENTS CONTENTS
elm.setAttribute('download', filename); // SET ELEMENT CREATED 'ATTRIBUTE' TO DOWNLOAD, FILENAME PARAM AUTOMATICALLY
elm.click(); // TRIGGER ELEMENT TO DOWNLOAD
elm.remove();
}
catch(err) {
console.log(err);
}
}
To call the function in code I've used anonymous function (normal func I hope also can be used):
(async () => {
await download('/api/hrreportbyhours',"Report "+getDDMMYYY(new Date())+".xlsx");
await setBtnLoad1(false);
})();
Upvotes: 2