There are already few questions like the one I am asking and I tried those approaches but they didn’t work for me, maybe I am missing something and hence I am asking a new question.
I am calling an API in my typescript application, the API returns me an object which has a field containing the byte array representation of a file. Here’s how the response model looks
{
"fileName": "Pokemon.xlsx",
"fileData":"this is the byte array representation of the file",
"fileContent":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}
In my typescript component I am calling the API and converting the JSON response into a response interface, this given code is what I referenced from other links
this.pokemonService.getExcel(REQUEST_OBJECT).subscribe((response) => {
if (response) {
const bytes = new Uint8Array(Buffer.from(response.fileData));
const fileBlob = new Blob([bytes], { type: response.contentType });
if (fileBlob.size > 0) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = `${response.fileName}`;
link.click();
}
} else {
//show error
}
});
given is the response interface that I cast the response to
export interface PokemonResponse {
fileData: ArrayBuffer;
fileName: string;
contentType: string;
}
The issue with the above code is that when I open the excel it shows that the file is corrupted,
I also tried converting the fileBlob in the above code to a File object using the below code but still the same result, the downloaded file when opened with excel shows as corrupted.
const file = new File([bytes], response.fileName, { type: response.contentType });
One thing I notice is that the ArrayBuffer contains a string representation (base64 is what I am guessing) of the file whereas the API is returning an array of bytes.
I tried to call the API directly using a C# console application and in the console app, it works as expected, the excel file is created and I can open and view the data without any corrupt file alert.
I feel like I am close to the solution but I am missing something here with regards to ArrayBuffer. Please suggest.
EDIT: Adding screenshot of the byte comparison of C# console app vs typescript app
Console app:
and here’s a presentation of the byte I get in the typescript application, note that I am printing the bytes variable shown in the code above which is a Uint8Array,
on observing both the byte representation it seems that the bytes are not in the same sequence, I think the Uint8Array conversion could be disturbing the sequence in typescript.
Advertisement
Answer
After spending some time I was able to resolve the issue.
I found that we have to explicitly mention the type of data the browser is supposed to parse and return, so before returning the response from the service in angular, I updated the content type with the following code
contentType: `data:${response.contentType};base64,`
Please note that contentType is a property of the PokemonResponse interface as shown above.
once I did this, the file was downloaded successfully. I assumed that this was already done by the browser but I was wrong.



