I have a Web API controller that looks like this:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using System.Threading.Tasks;
using System.IO;
namespace APIIntegration.Controllers
{
public class TestController : ApiController
{
// http://localhost/api/test
[HttpGet]
public async Task<HttpResponseMessage> Get()
{
Stream stream = streamWith256Bytes;
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentLength = stream.Length;
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "foo.bin";
return result;
}
private static Stream streamWith256Bytes
{
get
{
MemoryStream stream = new MemoryStream();
for (int i = 0; i <256 ; i++)
{
stream.WriteByte(Convert.ToByte(i));
}
stream.Position = 0;
return stream;
}
}
}
}
In short, this controller attempts to download a 256 byte file to the browser. At first, it appears to work, but when the downloaded file is examined, the size is 512 bytes instead of the expected 256 bytes and the non-printable characters are trashed.
How can I modify this code so that binary data may be downloaded correctly?
Edit: I should also mention that I saw a similar question here: Problems with downloading pdf file from web api service where the problem was fixed by adding a content-length header, but that didn't solve this for me.
Edit: I modified the source code above to give a complete, working example of how to reproduce.
Edit: I've discovered that the above code actually works correctly when I key in the address in the address bar, but when using Javascript to initiate the download, that's where I'm having a problem.
I have found a solution. In my Javascript, I used Angular to initiate a file download using the Angular $http service. By default, this service interprets the response as text. I had to tell Angular to interpret the response as a blob, and that fixed everything.
My working code looks like this:
function download(downloadUrl) {
$http({
url: downloadUrl,
responseType: "blob"
})
.then(function (response) {
var blob = new Blob([response.data], { type: "application/octet-stream" });
saveAs(blob, "foo.bin");
}, function (response) {
alert("error downloading file from " + downloadUrl);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With