Win a copy of Testing JavaScript Applications this week in the HTML Pages with CSS and JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

Download an xlsx file with reactJS: Excel can not open file

 
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to download an xlsx file with reactJS but i'm receiving this message when i try to open my file after download:

"Excel can not open file 'file.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the file format"

Here's the frontend code



Why am i getting this error? Please somebody help me, i'm stuck on this for 3 weeks
 
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi thomas, welcome to the Ranch!

So, that code is supposed to download a file from the server? I assume it's actually writing something to the client system because otherwise you'd be getting a different error message. So I would start by comparing the file downloaded to the client system versus the file on the server. First of all they should be the same size, and second they should contain the same data.
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:Hi thomas, welcome to the Ranch!

So, that code is supposed to download a file from the server? I assume it's actually writing something to the client system because otherwise you'd be getting a different error message. So I would start by comparing the file downloaded to the client system versus the file on the server. First of all they should be the same size, and second they should contain the same data.



Thanks for the reception! The file that i'm trying to download is build on backend, basically i get the values on database and use the Apache poi workbook to create the excel sheet. I will show you the mainly parts of the code:


1) This method is called by frontend on the first GET requisition of frontend and aims to prepare the file before the download. Is very simple, just create a token (buildToken()) and associate a temp file with this token (createTempFile(randomBackendToken)). The temp file is filled with what i get on my database (createFile(os))


@RequestMapping(value = "/token", method = RequestMethod.GET)
public String returnToken() throws IOException {

String randomBackendToken = tokenGenerator.buildToken();
OutputStream os = tokenGenerator.createTempFile(randomBackendToken);
tokenGenerator.createFile(os);

return randomBackendToken;

}



2) The method where i create the temp file:




3) The method where i receive the empty temp file and fills with my data on database:



4) My WriteExcel Class that build the xlsx file:



So, this all above is just for the first GET requisition. I make another one and the method below holds the second requisition. I just verify the token that the frontend returns for me and them, based on the validation, i allow the download of the file that i created on the previous step:

public void export(@PathVariable(value = "frontendToken") String frontendToken, HttpServletResponse response) throws IOException {

if (StringUtils.isNotBlank(frontendToken)) {

String tmpdir = System.getProperty("java.io.tmpdir");


File folder = new File(tmpdir);
File[] listOfFiles = folder.listFiles();


for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
boolean fileIsValid = tokenGenerator.validateToken(frontendToken, listOfFiles[i]);

if (fileIsValid) {

InputStream input = new FileInputStream(listOfFiles[i]);
OutputStream output = response.getOutputStream();

int data = input.read();

while (data != -1) {

output.write(data);
data = input.read();

}
input.close();
output.flush();
output.close();

String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.setContentType(mimeType);

listOfFiles[i].delete();
}
}
}

}

}



And that's all that i'm doing. Can't find what's wrong or what i'm missing. When i press F12 on my navigator to see the response of the request, shows for me something encoded, like:

PK@SM _rels/.rels­’ÁjÃ0 †_ÅèÞ8í`ŒQ·—2èmŒî4[ILbËØÚ–½ýÌ.[Kì($}ÿÒv?‡I½Q.ž£uÓ‚¢hÙùØx>=¬î@ÁèpâH"Ã~·}¢

Any suspicions of what can be?
 
Rancher
Posts: 4619
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, set the content type before sending any data.
Second, do not close the output stream.  That is handled by stuff on the server higher up the call chain.

Indeed, closing the output stream and then setting content type means that content type is not sent.
At least I'm pretty sure that would be the case.

You don't actually need to call flush either.
 
Dave Tolls
Rancher
Posts: 4619
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hang on.
Are you potentially sending multiple files there as well?
In the single stream?
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:First, set the content type before sending any data.
Second, do not close the output stream.  That is handled by stuff on the server higher up the call chain.

Indeed, closing the output stream and then setting content type means that content type is not sent.
At least I'm pretty sure that would be the case.

You don't actually need to call flush either.



Hello, Dave! Thanks for replying, i see your point, when i was reading your answer i thought that it was the solution for my problem but i made the changes and still getting the same error "Excel can not open file 'file.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the file format". Changed code follows below:



Did i miss something?
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:Hang on.
Are you potentially sending multiple files there as well?
In the single stream?



I have a list of temp files because i'm imagining the scenario of different users requesting the exportation but the idea is just send one file for each requisition, not multiple files
 
Dave Tolls
Rancher
Posts: 4619
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, but that won't work (the multiple files)...so that looping code may as well be removed.

As for the immediate problem, the next step is to check the file as downloaded compared to the one stored on the server, as suggested by Paul.
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:OK, but that won't work (the multiple files)...so that looping code may as well be removed.

As for the immediate problem, the next step is to check the file as downloaded compared to the one stored on the server, as suggested by Paul.



The problem in the process to compare the files is that:

1) I can't open my current file (the downloaded one), as i said, i receive an error message

2) There is no file stored on server, i create the file by my own geting data from database and writing the data on excel sheet
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried opening my downloaded file using OpenOffice instead of Microsoft Office 2013 and i could open the file but it showed the text "undefined" as content. Don't know if is a useful information to solve the problem but i'm sharing. I'm still stuck

 
Paul Clapham
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would suggest taking that code which builds the XLSX, and have it write the result to a local file. See if that produces a valid XLSX, and if it doesn't then fix the problem. Only when that's working should you test the code which sends the data (which you now know is valid data) over the network.
 
thomas topázio
Greenhorn
Posts: 22
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I will follow your advice, Paul. I will be back to tell which results i achieved. Thanks!
 
Dave Tolls
Rancher
Posts: 4619
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

thomas topázio wrote:
The problem in the process to compare the files is that:

1) I can't open my current file (the downloaded one), as i said, i receive an error message

2) There is no file stored on server, i create the file by my own geting data from database and writing the data on excel sheet



You don't need to compare the files that way.
The first step is are they the same size.

As for (2), I must have misunderstood you as I thought you'd opened the file on the server.
And the file is on the server, since it's created in the tmp folder.  It should still be accessible.
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello, Paul and Dave. Thanks to you two i found a new clue for my problem:

1) Contextualizing: When i press F12 on my navigator. i see the value of my token generated by the first GET requisition, for example 8fc62486d958471, and i also can see an encoded response associated with this token, you guys remeber that i talked about this encoded response previously?

2) Well, i discovered that this encoded response is an excel file on my temp folder and it is my file that supposed to be downloaded, i opened the file and saw my sheet correctly

3) But what is happening is that the file that is downloaded and sent to download folder is another, for example  e73589da-da3b-450a-98f2-aa6364f1d0ef, and is this one i can't open because shows the message that made me post my question in coderanch


So basically i have two files: The correct one that is on my temp folder and the wrong one that is on my download folder. I'm closer to solve my problem but i don't know what this information means, i'm trying to figure out.
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One more thing that i discovered: While debuging my frontend (you can see the full code on my first post),




The bold line had undefined value because i didn't need the _body , my_file is the body itself. So i tried:



And discovered that blob's size is different from my_file's size. I guess that the problem that i have is because of encoding while reading the binary data
 
Paul Clapham
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By "encoding" I would hope that you are talking about URL-encoding. Is that right? Converting from bytes to chars, or vice versa, would be a bad thing since the data isn't text.
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:By "encoding" I would hope that you are talking about URL-encoding. Is that right? Converting from bytes to chars, or vice versa, would be a bad thing since the data isn't text.



Yes, Paul. That's what i mean, my binary data is being converted for string and this is breaking my excel file. The problem is on frontend, not backend (that's why the excel on temp folder is ok but the excel on download folder isn't). I'm trying to do something on my Rest.ajaxPromise(). Actually is like that:



So i guess i need to change this, something like:



But i don't if will work, i'm trying
 
thomas topázio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, guys!

As i said before: my binary data was being converted for string by javascript and this was breaking my excel file. My try on Rest.ajaxPromise() didn't worked so i solved my problem converting my binary data on backend to text and then on frontend i make the inverse. The following links helped me:

https://stackoverflow.com/questions/42667942/java-convert-inputstream-to-base64-string

https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript



Thank you for everyone that tried to help. I hope my question can help others
 
    Bookmark Topic Watch Topic
  • New Topic