I am currently attempting to download a Word document from my angular 5 application. The docx file sits in a template folder on the server, and it opens without a problem from the server. But when I retrieve it in my application, send it to the client, and then call saveAs to download it, it downloads, but the file opens corrupted. I have had a look at a whole bunch of other issues but haven't come across one that covers this scenario. I suspect it might be some sort of encoding issue.
In my controller, the code looks like this:
[HttpGet("[action]")]
public IActionResult GetGdwFile([FromBody] int gdwQueryJobId)
{
var currentDirectory = Directory.GetCurrentDirectory();
var filePath = Path.Combine(currentDirectory, @"DocumentTemplates\nab.docx");
var fileData = System.IO.File.ReadAllBytes(filePath);
return Ok(new Models.APIResult {Success = true, Data = fileData});
}
Within the angular client side code, my call looks like this:
downloadFile() {
this.gdwService.getGdwFile(1).subscribe(response => {
const fileBlob = new Blob([response.data], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
saveAs(fileBlob, "Salesbypostcode.docx");
});
}
When I debug, response.data does contain the full binary data array, as expected.
The gdwservice call is just a straight through http get:
getGdwFile(gdwQueryJobId: number) {
return this.http.get(`/api/Gdw/getGdwPdfFile?gdwQueryJobId=${gdwQueryJobId}`,
{
headers: new HttpHeaders({
"Content-Type": "application/json",
})
});
}
What do I need to do to get this downloading properly without the file turning up corrupted?
Ok, I've found an answer to my problem. When the data is returned from the service method, it doesn't appear to be encoded properly. To solve that, I did the following:
downloadGdwFile() {
this.gdwService.getGdwFile(1).subscribe(response => {
const byteCharacters = atob(response.data);
var byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
saveAs(blob, "Salesbypostcode.docx");
});
}
I got the idea from the answer of this stack overflow issue
You have to be careful, though, if the file is large, as is mentioned in that issue.