nico

11 Mar 2022

Axios download CSV from web api returns error : TypeError: Cannot read properties of null (reading '1')

Javascript

Hello all I use the following code to make axios make download the file csv:

I have in response.data

data: "Date;Provider;BookingNumber;PNR;Action;PCC;CountryID;Savings;OriginalFare;NewFare;BONewFare;PerCentageDifference;IsPublicOrNetFare;AcctCorpCode;OPcc;PlatingCarrier;RebookedCarrier;Routes;Queue;Online_Offline;LastPurchase;MaxRebook\r\n2022-01-01 01:16:19;Galileo;;0T9FKX;optimization;;;60.00;458.69;398.69;398.69;0;False;;36PR;HC;;;60;False;1/1/2022 1:16:19 AM;\r\n2022-01-05 16:31:24;Galileo;;0TXVHJ;optimization;;;50.00;821.67;771.67;771.67;0;False;;36PR;HC;;;60;False;1/5/2022 4:31:24 PM;\r\n2022-01-11 12:38:18;Galileo;;0VRRH4;optimization;;;18.00;246.40;228.40;228.40;0;False;;36PR;TU;;;60;False;1/11/2022 12:38:18 PM;\r\n2022-01-12 12:51:51;Galileo;;0VYC6S;optimization;;;44.00;549.14;505.14;505.14;0;False;;36PR;ET;;;60;False;1/12/2022 12:51:51 PM;\r\n2022-01-13 12:25:38;Galileo;;0W3CXR;optimization;;;106.00;722.75;616.75;616.75;0;False;;36PR;TK;;;60;False;1/13/2022 12:25:38 PM;\r\n2022-01-14 20:19:16;Galileo;;0WB0RG;optimization;;;18.00;226.37;208.37;208.37;0;False;;36PR;TU;;;60;False;1/14/2022 8:19:16 PM;\r\n2022-01-19 19:47:47;Galileo;;0X25Q2;optimization;;;30.00;280.40;250.40;125.20;50,0;False;;36PR;TU;;;60;False;1/19/2022 7:47:47 PM;\r\n2022-01-24 13:20:31;Galileo;;0XRVDR;optimization;;;228.00;1767.09;1539.09;513.03;66,666666666666666666666666670;False;;36PR;HF;;;60;False;1/24/2022 1:20:31 PM;\r\n"

 axios.post(url, obj)
 .then(response => {


 
 var blob = new Blob(
 [response.data], // Blob parts.
 {
 type: "text/csv;charset=utf-8"
 }
 );

 

 const url = window.URL.createObjectURL(blob);
 const link = document.createElement('a');
 link.href = url;

 var contentDisposition = response.headers["content-disposition"];
 var match = contentDisposition.match(/filename\s*=\s*"(.+)"/i);
 var filename = match[1];

 link.setAttribute('download', filename); //or any other extension
 document.body.appendChild(link);
 link.click();
 document.body.appendChild(link);
 })
 .catch(error => {
 dispatch(errorData());
 alert(error);
 //TODO: handle the error when implemented
 })
 }

Can you tell me what is going on?

Thanks

Comments

Mohamed Atef

11 Mar 2022

githubgithubgithub

Can you please add console.log after creating the blob then console.log to get the value of the URL, I belive that the error is coming from these 3 lines 

var contentDisposition = response.headers["content-disposition"];
var match = contentDisposition.match(/filename\s*=\s*"(.+)"/i);
var filename = match[1]; 

also I can share an example i did before to get download the CSV

let res1 = await axios.get(BackendURL+'/api/files/download/'+this.state.currentDocument?.documentId, conf);
let blob = new Blob([res1.data], {type: 'application/pdf'});
const fileURL = window.URL.createObjectURL(blob);
this.setState({ currentDocumentURL: fileURL });

please note that type is ‘application/pdf’ i need to change it if I will display the response but to get the URL you can use any type

nico

11 Mar 2022

Hello Mohamed It was a problem of regular expression,

what is the best way of getting the filename from the content-disposition ?

Moreover as to avoid reinventing the code to make the file downloading automatic: I use the js-file-download npm:

//www.npmjs.com/package/js-file-download


 

 

import fileDownload from 'js-file-download';

 axios.post(url, obj)
 .then(response => {

 fileDownload(response.data, 'report.csv')
 })
 .catch(error => {
 dispatch(errorData());
 alert(error);
 //TODO: handle the error when implemented
 })

Replies

Mohamed Atef

11 Mar 2022

githubgithubgithub

I don't think you need to use "content-disposition", why you need to use it 

nico

11 Mar 2022

Because the file name is generated by the backend so the js client needs to read it from content-disposition header.

For example: 

Report-20220311.csv 

The server generate the name with the date and sends in the content-disposition header

 

 return new FileContentResult(result,"text/csv")
 {
 FileDownloadName = $"Report{DateTime.Now.ToString("YYYYmmdd")}.csv"
 };

Replies

Mohamed Atef

11 Mar 2022

githubgithubgithub

You can set different names to the files from the frontend when the user download it 

© 2023 Copyrights reserved for web-brackets.com