I am able to download the file from specific URL. But here problem is this file getting saved inside the download folder of the system. Is there any way to save this file locally in project and read this file programmatically?
const downloadFile = () => {
fetch(urlToDownload)
.then(response => {
response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'example.pdf';
a.click();
});
});
}
Related
I got Node JS server which gets XLSX file contents from metabase:
app.get('/channels', async (req, res) => {
// make request to metabase and take response as XLSX
const queryRequestURL = `${api}/public/card/${cardId}/query/xlsx?parameters=${params}`;
const result = got(queryRequestURL);
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader("Content-Disposition", "attachment; filename=file.xlsx");
return res.send(res);
});
It returns file contents like
So when i make request to server and receive response - it comes as file contents above.
I need to download this data as ordinary excel file on browser side.
What i've tried:
// make request with typical fetch and get result to res variable.
const filename = 'file.xlsx';
const file = new File(res, filename ,{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
// create link and click it virtually to download created file
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = filename;
a.click();
But I'm getting the error:
Uncaught (in promise) TypeError: Failed to construct 'Blob': The provided value cannot be converted to a sequence.
I think that I'm doing something wrong and there is more simple way to download file.
Without seeing how you're fetching, it's hard to know. But you should be able to use response.blob() to download the result.
fetch("${api}/channels}", {
method: "GET",
})
.then((response) => response.blob())
.then((blob) => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url;
a.download = "file.xlsx";
document.body.appendChild(a);
a.click();
a.remove();
});
As Joey Ciechanowicz mentioned, we should return response.buffer() from backend and work with its data as blob at frontend.
I mean
NodeJS side (using Got):
const result = got(queryRequestURL, {
headers: headers
});
return await result.buffer()
Frontend side (pure JavaScript):
// fetch data
const result = await fetch(api + path);
return result.blob();
// download file
const filename = 'export.xlsx';
var url = window.URL.createObjectURL(result);
var a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
a.remove();
I have been trying to figure out how can I create a download functionality when a user clicks on a button.
I tried to use the File save library but the result is not as expected, also I tried a turnaround and used a different approach but again the same.
When I download the file using the 2nd approach that is by using fetch API the file am getting is a corrupted file.
Please see the code below with the codeSandbox link as well.
Approach 1
const onDownload1 = () => {
saveAs("../../testFile.docx", "testFile.docx");
};
Approach 2
const onDownload2 = () => {
fetch("../../testFile.docx").then((response) => {
response.blob().then((blob) => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = "testFile.docx";
a.click();
});
});
};
Full source code link
Click to open in codeSandbox.
Thanks for the help and time.
With "../../testFile.docx" the app is attempting to serve the file from a relative path from where the app is being hosted and served from. The testFile.docx file needs to be accessible and served correctly.
If serving file from the public folder
Place testFile.docx in the public directory.
/public
+-/files
+-testFile.docx
Use an absolute path to access the testFile.docx file.
Examples:
Approach 1
const onDownload1 = () => {
saveAs("/files/testFile.docx", "testFile.docx");
};
Approach 2
const onDownload2 = () => {
fetch("/files/testFile.docx").then((response) => {
response.blob().then((blob) => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = "testFile.docx";
a.click();
});
});
};
If imported and used locally
import file from './testFile.docx';
Approach 3
const onDownload3 = () => {
saveAs(file, "testFile.docx");
};
Approach 4
const onDownload4 = () => {
fetch(file).then((response) => {
response.blob().then((blob) => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = "testFile.docx";
a.click();
});
});
};
I'm building an application using Angular 10. I have a function that downloads files from a local server. This function works fine for extensions - .PDF, .xlsx, etc. , except files with .msg extension. On download, it returns a file of size 0KB.
This is my function:
downloadFile(url:string,fileName:string){
fetch(url)
.then(res => res.blob())
.then(blob => {
var a = document.createElement("a");
document.body.appendChild(a);
a.style.display = "none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
});
}
I tried to use these headers but still, it didn't work:
application/octet-stream
application/download
How do I resolve this problem?
Use application/vsd.ms-outlook as MIME type for .msg extension.
I am trying to make a JavaScript/HTML local webpage that just gets opened from my local computer's files. I would like to make it save data in JSON form. But I've been having trouble finding out how to make a local JavaScript program read and write to a file in its same directory.
You can not write files to the local machine if you're using Javascript in the browser.
But you can download the JSON file to your local machine using Blob
You can use this code:
const data = {
key: "value"
};
const fileName = "data.json";
const saveFile = (() => {
const a = document.createElement("a");
document.body.appenChild(a);
return (data, filename) => {
const json = JSON.stringify(a);
const blob = new Blob([json], { type: "application/json" });
const url = window.URK.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}
})
saveData(data, fileName);
I have a link /api/ticket/1/download to my server and if I copy paste it into the browser, it will start a download of my file with it's filename extension and everything set up already.
How can I do it in javascript? With thymeleaf i was just using <a href="myLink"> and it worked like if I paste it in the browser. But due to react-router a href just goes to another page.
But if I use await fetch like this:
let url1 = '/api/ticket/' + fileId + '/download';
const response = await fetch(url1);
const blob = response.blob();
const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `file.jpg`);
document.body.appendChild(link);
link.click();
i can transfer response into blob, but then i miss the files name and extension.
The only way to solve this that i found is: send file name and extension in a response header and than parse them manualy.
like:
in spring:
myControllerMethod( HttpServletResponse response){
...
response.setContentType(att.getType());
response.setHeader("Content-Disposition", "attachment; filename=\"" + myFileName + "\"");
}
in react:
const headers = response.headers;
const file = headers.get("Content-Disposition");
and then parse manully this 'file' to get filenamel;
Try in this way, it may help you :
fetch('http://localhost:8080/employees/download')
.then(response => {
response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'employees.json';
a.click();
});
For more reference you can go through This link