REACT: download a file with Axios using a progress bar - reactjs

I have an application that downloads a zip file in this way. It works regularly but when clicked, the download is performed in the background and the browser shows the actual download of the file only when the whole stream has been downloaded locally. So if the file takes 1 minute to download, the user doesn't understand what the site is doing. Is there any way to show a progress bar?
await axios({
url: sUrl,
method: "GET",
responseType: "blob" // important
})
.then(response => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", fname); //or any other extension
document.body.appendChild(link);
link.click();
this.setState({ downloading: false });
})
.catch(error => {
this.setState({ downloading: false });
message.warn("Errore: " + error.message);
return [];
});

Yes, you can achieve this by using onDownloadProgress method provided by axios package, check the below example :
await axios({
url: sUrl,
method: "GET",
responseType: "blob", // important
onDownloadProgress: (progressEvent) => {
let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total); // you can use this to show user percentage of file downloaded
}
})

Axios package has both onDownloadProgress and onUploadProgress to show a progress bar during download or upload, have you tried them?
I recommend you to have a quick look at this Tutorial

Related

React - Download image from url without saving it to filesystem and send it to Node Api

We have requirement where we have to read 1-10000 image URL from one location. Sample array
[
{
"asin": "B00HZ9Q8XM",
"image": "https://m.media-amazon.com/images/I/41gKlxTYnkL._SL500_.jpg"
},
{
"asin": "B00JOW20TY",
"image": "https://m.media-amazon.com/images/I/511Ae304D5L._SL500_.jpg"
}
]
We need to loop through above array, download or read image, call an external node api which will accept image as file with multipart/form-data and file type can only be jpg
We wanted to do this without saving files on local server as there will be 100 of such request and don't want to fill up server space.
What we tried so far, we can download image as blob or arrayBuffer like following;
export const downloadImageFromUrl = async(url) => {
// const response = await fetch({
// url,
// method: 'GET',
// responseType: 'stream'
// });
const response = await axios({
url,
method: 'GET',
responseType: 'blob'
});
console.log('response ', response)
//fs.writeFileSync('./temp.jpg', res.data);
return response;
}
But when we send it to node api, it says filetype is blob and reject our request. Can you please advise best approach to achieve this ?
Just use the arraybuffer response type.
P.S. Blobs are not currently supported by Axios on the Node.js platform;
const response = await axios({
url,
method: 'GET',
responseType: 'arraybuffer'
});

How to upload local video file to Google Cloud

I am stuck with a file upload process in a react app. In the app, I am trying to upload local video files to Google Cloud Storage.
I take the input file from:
<input type={`file`} accept=".mp4" onChange={VideoSelectChangeFunc} />
In VideoSelectChangeFunc, I get the local URL of the input file by,
let file = URL.createObjectURL(event.target.files[0])
Then I use it in axios to send to cloud
export const UploadVideo = async (file, signedurl, asset_uuid) => {
let resultState = { state: '', data: {} };
await axios({
method: 'put',
url: signedurl,
data: file,
headers: {
'Content-Type': 'application/octet-stream',
},
}).then(function (response) {
resultState.state = 'success';
resultState.data = response.data
}).catch(function (error) {
resultState.state = 'error';
resultState.data.message = error.message;
window.toastr.error(error.message);
console.log(error)
})
return resultState;
}
What I see on cloud is:
blob:http://localhost:3000/9b650cbf-8b49-440b-9e90-da6bdb5d392a
This is just the local URL of the file as string but not the video itself, when I copy and paste it on browser I can see the video. I searched the situation and saw 'Content-Type': 'blob' would solve the problem. However, we are checking headers in our CORS Policy, so it has to be 'Content-Type': 'application/octet-stream'. Is there a way to work this out?
Before sending it, converting the blob url into file worked. I have only added these two lines then, called axios.
let blob = await fetch(blobURL).then(r => r.blob());
var file = new File([blob], "thisVideo.mp4",{type:"video/mp4", lastModified:new Date().getTime()})
This can be useful, in the situations where the file is not uploaded right away but the url saved temporarily to be called later on which was the case here. If you are interested visit this question too:
How to get a file or blob from an object URL?

How to download multiple files with Axios?

async function download(stuff) {
if (stuff.length > 1) {
//What do I do?
} else if (stuff.length === 1) {
const link= stuff[0];
axios({
url: `/link`,
method: "GET",
responseType: "blob", // important
}).then((response) => {
let url = window.URL.createObjectURL(new Blob([response.data]));
let a = document.createElement("a");
a.href = url;
a.download = "myFile.jpg"
a.click();
});
}
}
I use this and it works fine when I want to download a single file. But if stuff contains more elements, I would like to download them all. One after another doesn't work well, as the user has to confirm them separately. So, I would like to download them all together as a zip file. Is there a recommended method how to do that?

Pop-up when a pdf is download in IE11

I get a pop-up "Do you want to allow this website to open an app on your computer?" in IE11 when a pdf is downloaded.
With the code below in angularts the correct pop-up is opened "Do you want to open or save the file"? But also "Do you want to allow this website to open an app on your computer?"
const headerOptions = new HttpHeaders({
// 'Cache-Control': 'private',
// 'Content-Disposition': 'attachment; filename = ' + filename,
'Content-Type': 'application/pdf'
});
const requestOptions = {
headers: headerOptions,
responseType: 'blob' as 'blob'
};
this.http
.post(
`${this.url}?id=${id}&datasource=${datasource}&device=${device}&browser=${browser}&link=${link}`,
dataObj,
requestOptions
)
.catch(error => {
return this.clickHandlerError(error);
})
.pipe(
map((data: any) => {
const blob = new Blob([data], {
type: 'application/pdf'
});
window.navigator.msSaveOrOpenBlob(blob, filename);
})
)
.subscribe((result: any) => {});
I expect to have just the correct pop-up to open or save the file.
This is a client side error message letting the user know that this action will cause an application to open on the user's system. If you want this to stop then you'll need to configure the client machine not the web application.
I suggest you to check your IE options and disable this prompt.
If issue persist than you can reset your IE application can help to fix this issue.

download file in react

i have an Restful API i created using Laravel, this API like this:
http://127.0.0.1:8000/api/file/pdf/{id}
and this is my code for download:
public function pdfDownload($id){
$pdf = Cv::findOrfail($id);
return Storage::download('public/pdf/'.$pdf->pdf);
}
it is worked in postman, and also in browser, it is directly download the file,
but with react.js, it is not work, this my code in react:
pdfDownload = (id) => {
fetch(' http://127.0.0.1:8000/api/file/pdf/' + id, {
method: 'get',
headers: {
Accept: 'application/octet-stream',
'Content-Type': 'application/octet-stream'
}
}).then((res) => res.json());
};
and i call this function in button like this :
<Button color="primary" onClick={() => this.pdfDownload(data.id)}>
Download
</Button>
the id is corrected, i am ensure from this, my question is how can i download file when click this button.. Thans...
XHR calls can not trigger file download, the way browser handles it. You will have to mimic a file download using javascript code yourself, using something like below:
Reference
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
Or use File Saver package, if you don't mind an extra dependency.
FileSaver Npm

Resources