Reputation: 613
I feel like I'm so close to getting this right.
In this example the file is 125 KB and of type image/png.
I have a C# controller method that constructs a HttpResponseMessage with a file as follows:
public async Task<HttpResponseMessage> Get(int id)
{
var file = await _api.GetFileAsync(id);
var httpResult = new HttpResponseMessage(HttpStatusCode.OK);
httpResult.Content = new ByteArrayContent(file.Bytes);
httpResult.Content.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
httpResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = file.Name
}; //attachment will force download
return httpResult;
}
The raw file itself is kept in the byte[] of file.Bytes
.
And here's a JavaScript function that calls it:
get(fileId, fileName) {
return this.httpFetch.fetch(`${this.apiRoot}/v1/files/${fileId}`)
.then(response => response.blob())
.then(data => {
if (window.navigator.msSaveOrOpenBlob)
window.navigator.msSaveBlob(data);
else {
var link = document.createElement("a");
link.href = window.URL.createObjectURL(data);
link.download = fileName;
document.body.appendChild(link); // Required for FF
link.click();
}
});
}
Here's a preview of the payload according to Chrome network tools. Seems kind of empty to me...
The type and filename are correct and it does auto-download, but I end up with a file that's 336 bytes and unreadable.
What am I missing here?
More Info: httpFetch
is a wrapper of fetch
by Aurelia (aurelia-fetch-client). I'm using Aurelia as my front-end framework.
Upvotes: 2
Views: 4742
Reputation: 613
I can't explain why my solution above didn't work, but some other tests have revealed that the problem is more likely than not in the back-end C# WebApi controller method as my payload can be seen missing... well... the file which is odd.
I've gone for a simpler solution, namely:
public async Task<IActionResult> Get(int id)
{
var file = await _api.GetFileAsync(id);
var obj = new
{
file.Name,
file.ContentType,
Base64String = Convert.ToBase64String(file.Bytes)
};
return new OkObjectResult(obj);
}
Notice how I'm returning an anonymous object with the name, content type and base64 string representation of the file. Pairing this with a solution on base64 to blob in JavaScript solves the problem nicely with minor alterations to the get
JavaScript function:
let blob = this.base64toBlob(data.base64String, data.contentType);
var link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
document.body.appendChild(link); // Required for FF
link.click();
resolve(blob);
Upvotes: 1