Download excel file created in node using SheetJS/XLXS [NodeJS] [React] - javascript

I'm trying to generate a xlsx file using SheetJS in node. Then in my frontend I have a button to call this route and download the file. Currently I have the following:
// backend code
export function exportExcel(req: Request, res: Response) {
try {
const workbook = utils.book_new();
const fileName = "sample";
const dataSheet = utils.json_to_sheet(sampleData);
utils.book_append_sheet(workbook, dataSheet, fileName.replace("/", ""));
const binaryWorkbook = write(workbook, {
type: "array",
bookType: "xlsx",
});
return res.status(OK).send(binaryWorkbook);
} catch (_error) {
return res.sendStatus(500)
}
}
Then in the front end I have the following:
const handleExcelExport = () => {
const { data } = await axios.get(
`/export-excel`,
{
responseType: "blob",
}
).then(response => {
const blob = new Blob([response], {
type: "application/octet-stream",
});
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
}
}
// I simply call the above in the onClick handler in a button
<button onClick={handleExcelExport}> Export excel </button>
I can see that a download file appears when I click on the button but I can't open it. MS Excel says that ""File format or file extension is not valid..."

I fixed by changing to the following in the BE:
const binaryWorkbook = write(workbook, {
type: "array",
bookType: "xlsx",
});
and also adding headers per the docs:
res.setHeader(
"Content-Disposition",
'attachment; filename="SheetJSNode.xlsx"'
);
res.setHeader("Content-Type", "application/vnd.ms-excel");
Then in the frontend I changed the response type and content-type to
{
responseType: "arraybuffer",
}
Blob content-type
const blob = new Blob([response], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});

Related

Download pdf from REST API with correct encoding

I'm trying to download pdf file from rest api using those two methods:
download(): ng.IPromise<Blob> {
return this.$http.get<ArrayBuffer>(this.urls.getUrl())
.then(response => {
return new Blob([response.data], {type: 'application/pdf'});
}
)
}
this.service.download().then( file => {
var a = document.createElement("a"),
url = URL.createObjectURL(file);
open(url)
a.href = url;
a.download = 'invoice';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
And there appears to be some problem with the encoding of created Blob. If I call this endpoint from Postman and select "save response" then "save to a file", I get the correct pdf. When I use the presented code, file seems to be incorrectly encoded (opened with vim has generally similar structure, but different symbols).
In service you can use httpOptions like this:
download() {
const httpOptions = {
responseType: 'blob' as 'json',
};
return this.http.get<any>(
ServerUrl + `/api/getfile`,
httpOptions
);
}
also on you component you can call service and download the pdf like this:
this.api.download().subscribe(
(idata) => {
let blob = new Blob([idata], { type: 'application/pdf'
});
var downloadURL = window.URL.createObjectURL(idata);
var link = document.createElement('a');
link.href = downloadURL;
link.download = 'invoice.pdf';
link.click();
},
async (err) => {
}
);

Download Excel File From Server - Angular

Trying to download excel (.xlsx) file from my restAPI.
This is my code -
let headers = new Headers();
headers.append('Content-Type', 'application/vnd.openxmlformats');
this.http
.get(
`${pathToExcel}`,
{ headers: headers, responseType: ResponseContentType.Blob }
)
.subscribe((res: any) => {
let blob = new Blob([res._body], { type: 'application/vnd.openxmlformats' });
let myUrl = document.createElement('a');
myUrl.href = window.URL.createObjectURL(blob);
myUrl.download = 'Log.xlsx';
let event = document.createEvent('MouseEvent');
event.initEvent('click', true, true);
myUrl.dispatchEvent(event);
});
The file is downloaded but it's empty.
What am I missing?

octet-stream on angular - file download not working

I am trying to download a file on a button click, api have been hit successfully am getting 200 response, but file is not being downloaded. It's working on postman.
My code is shown below
/**** click */
downloadAsset() {
this.detailsService.getCsvReport(this.jobId).subscribe(data => {});
}
/**** Service */
getCsvReport(jobId): Observable<Object> {
const header = { Accept: "application/octet-stream" };
let endpoint: string = `${Endpoints.REPORT}jobs/${jobId}/filePath?`;
return this.get(endpoint, header).pipe(
map(report => {
return report.data.parentXml;
})
);
}
<button
class="btn btn-blue-border"
style="float: right;"
(click)="downloadAsset()"
>
Download Report
</button>
Any changes or suggestion's would be appreciated.
You can try like this
getCsvReport(jobId): Observable<Object> {
const header = { Accept: "application/octet-stream" };
let endpoint: string = `${Endpoints.REPORT}jobs/${jobId}/filePath?`;
return this.get(endpoint, header).pipe(
map(report => {
const a = document.createElement('a');
document.body.appendChild(a);
const blob: any = new Blob([report.data.parentXml], { type: 'octet/stream' });
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = data.fileName;
a.click();
window.URL.revokeObjectURL(url);
})
);
}
I think you need to set the response type of your request.
An example with http.post:
this.http.post(url + "/getFile", params, { responseType: "blob" }).subscribe(...)
I hope i can help.

"blob".then is not a function when trying to generate pdf in react js

I am sending the below response from my REST Api .
{
"value": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9TL0phdmFTY3JpcHQvSlModGhpcy56b29tID0gMTAwOyk+PgplbmRvYmoKNSAwIG9iago8PC9Db2xvclNwYWNlL0RldmljZUdyYXkvU3VidHlwZS9JbWFnZS9IZWlnaHQgMTUwL0ZpbHRlci9GbGF0ZURlY29kZS9UeXBlL1hPYmphkNkwEVng0L00DhlcQ6ysIV4GNaOajLDQGlbKEIuFcJchdvr0W/z0aY+lZJyy+pmGsnrODq3AQiAQCAQCiRDHKaRFx0iOEAGhh40g1P0IsjS9pXbPlEzDoYf1OKTkDjFdQ6ysIXaYzMRC17KaLtIpQxdTKUPs9Gm646LMQnT6NJeFXjazUIotCx3mrcWQabf6qG8iEAgEAoEmsW7jOIXU6BidLK2BkEZBFP88qhr9R42IKBwiqdSMSBnlGjL2GlLDZOZqMuuUIZsuQ5bp0/xSMkdl9YZdyfy1GOK2W4z6JgKBQCAQaBJLFyDTZwphpxCJjpHQGGYbPAn/JQ/DX/YVtf/Rq19v18QeBP+Sh+Gv+wra/+jVr7foAKKKKACiiigD5g/aO/wCSh6f/ANgqP/0bLXj9ewftHf8AJQ9P/wCwVH/6Nlrx+gAooooAK6DwJ/yUPw1/2FbX/wBGrXP10HgT/kofhr/sK2v/AKNWgD7fooooA8f/AGjv+Seaf/2FY/8A0VLXzBX0/wDtHf8AJPNP/wCwrH/6Klr5goAK+n/2cf8Aknmof9hWT/0VFXzBX0/+zj/yTzUP+wrJ/wCioqAPYKKKKACiiigAooooAKKKKACiiigD5g/aO/5KHp//AGCo/wD0bLXj9ewftHf8lD0//sFR/wDo2WvH6ACvt/wJ/wAk88Nf9gq1/wDRS18QV9v+BP8Aknnhr/sFWv8A6KWgDoK5/wAd/wDJPPEv/YKuv/RTV0Fc/wCO/wDknniX/sFXX/opqAPiCiiigAooooAKKKKACiiigAooooA6DwJ/yUPw1/2FbX/0atfb9fEHgT/kofhr/sK2v/o1a+36ACiiigAooooAKKKKACviDx3/AMlD8S/9hW6/9GtX2/XxB47/AOSh+Jf+wrdf+jWoA5+ug8Cf8lD8Nf8AYVtf/Rq1z9dB4E/5KH4a/wCwra/+jVoA+36KKKAPH/2jv+Seaf8A9hWP/wBFS18wV9P/ALR3/JPNP/7Csf8A6Klr5goAK+n/ANnH/knmof8AYVk/9FRV8wV9P/s4/wDJPNQ/7Csn/oqKgD2CiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK4P4s+NdS8B+FbXVNLgtJp5b1LdlukZlClHbI2spzlB39a7yvH/wBo7/knmn/9hWP/ANFS0AcB/wANHeMP+gbof/fib/47R/w0d4w/6Buh/wDfib/47Xj9FAH0P4b8N2fx306TxR4okns761lOnpHpjCOMxqBICRIHO7Mrc5xgDj12P+GcfB//AEEtc/7/AMP/AMao/Zx/5J5qH/YVk/8ARUVewUAeP/8ADOPg/wD6CWuf9/4f/jVcRf8Axr8SeDtRufC+nWWlS2OjSvp9vJcRSNI0cJMalyJACxCjJAAz2FfS9fEHjv8A5KH4l/7Ct1/6NagD0D/ho7xh/wBA3Q/+/E3/AMdqnq3x98Vazo19pdxp+jLBe28lvI0cMoYK6lSRmQjOD6GvK6KACiiigD2D9nH/AJKHqH/YKk/9GxV9P18wfs4/8lD1D/sFSf8Ao2KvKACiiigAooooAKKKKACvmD9o7/8L0luZm8gMjQgMCBSL0lEIFs8YzkyMWI2MGVkYzdkYTVlZWQyMzYyNTliYWRiYTVjMGY+PDMzYWYzZTBkOGM1MjFhNzVlMjk2MGQwZDIzZjJkY2U2Pl0vUm9vdCAyMyAwIFIvU2l6ZSAyNT4+CnN0YXJ0eHJlZgoxODA2OTIKJSVFT0YK",
"transid": "transid"
}
I am trying to convert the value which is byte data to pdf using React js.
Below is my implementation:
handleSubmit = e => {
e.preventDefault();
let url = "http://localhost:8080/getPDF"
fetch(url, {
method: "POST",
body: JSON.stringify(this.state.transId),
})
responseType: 'blob'
.then(response => {
//Create a Blob from the PDF Stream
const file = new Blob(
[response.value],
{type: 'application/pdf'});
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
window.open(fileURL);
})
.catch(error => {
console.log(error);
});
};
But I am getting the following error.Can anyone please suggest where I am going wrong?
Uncaught TypeError: "blob".then is not a function
You cannot do .then() after a string (must follow a promise). You probably meant this line responseType: 'blob' to be one line higher up, inside the object?
handleSubmit = e => {
e.preventDefault();
let url = "http://localhost:8080/getPDF"
fetch(url, {
method: "POST",
body: JSON.stringify(this.state.transId),
responseType: 'blob' // <-- MOVE THIS LINE INTO REQUEST
})
.then(response => {
//Create a Blob from the PDF Stream
const file = new Blob(
[response.value],
{type: 'application/pdf'});
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
window.open(fileURL);
})
.catch(error => {
console.log(error);
});
};

Blank images and pdfs downloaded from Dropbox

I have a problem when downloading files from my dropbox.
While using the type 'text/csv' I can download and view txt files.
Chaning the type to 'image/jpeg' or 'application/pdf' and download the filetype gives me blank file.
Am I on the right track here or is there another way this should be done?
main.service.ts
downloadFile(id) {
const headers = new Headers();
headers.append('Authorization', 'Bearer ' + this.accessToken);
const path = `{"path": "${id}"}`;
headers.append('Dropbox-API-Arg', path);
return this.http.post('https://content.dropboxapi.com/2/files/download',
null, { headers: headers });
}
main.component.ts
downloadFileBlob(data: any, name) {
const blob = new Blob([data], { type: 'image/jpeg' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
saveFile(id, name) {
this.dropbox.downloadFile(id).subscribe((data: any) => {
this.downloadFileBlob(data._body, name); });
}
Turns out I was going at this the wrong way.
Dropbox github has an example of using sharingGetSharedLinkFile, which works about the same as filesDownload.
Replace sharingGetSharedLinkFile with filesDownload and provide a file path instead of the URL.
Something like this:
function downloadFile() {
var ACCESS_TOKEN = (<HTMLInputElement> document.getElementById('access-
token')).value;
var SHARED_LINK = (<HTMLInputElement> document.getElementById('shared-
link')).value;
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
dbx.filesDownload({path: SHARED_LINK})
.then(function(data) {
var downloadUrl = URL.createObjectURL((<any> data).fileBlob);
var downloadButton = document.createElement('a');
downloadButton.setAttribute('href', downloadUrl);
downloadButton.setAttribute('download', data.name);
downloadButton.setAttribute('class', 'button');
downloadButton.innerText = 'Download: ' + data.name;
document.getElementById('results').appendChild(downloadButton);
});
}

Categories

Resources