问题
I want to return an image from WebApi endpoint. This is my method:
[System.Web.Http.HttpGet]
public HttpResponseMessage GetAttachment(string id)
{
string dirPath = HttpContext.Current.Server.MapPath(Constants.ATTACHMENT_FOLDER);
string path = string.Format($"{dirPath}\\{id}.jpg");
try
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
var content = new StreamContent(stream);
result.Content = content;
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(path) };
return result;
}
catch (FileNotFoundException ex)
{
_log.Warn($"Image {path} was not found on the server.");
return Request.CreateResponse(HttpStatusCode.NotFound, "Invalid image ID");
}
}
Unfortunately, the file that is downloaded is incomplete. The message in consuming Android app is:
java.io.EOFException: source exhausted prematurely
回答1:
The problem is most likely that your Android client thinks the download is over before it actually is.
To easily fix this, you can use this method instead which will return the entire file at once (rather than streaming it):
result.Content = new ByteArrayContent(File.ReadAllBytes(path));
回答2:
Turns out that this was caused by compression, that was set for all responses in this controller. There is GZip encoding set up in controller's constructor:
HttpContext.Current.Response.AppendHeader("Content-Encoding", "gzip");
HttpContext.Current.Response.Filter = new GZipStream(HttpContext.Current.Response.Filter, CompressionMode.Compress);
To solve this, I added these lines to my method
(just after beginning of try
block):
// reset encoding and GZip filter
HttpContext.Current.Response.Headers["Content-Encoding"] = "";
HttpContext.Current.Response.Headers["Content-Type"] = "";
// later content type is set to image/jpeg, and default is application/json
HttpContext.Current.Response.Filter = null;
Also, I'm setting content type and length like this:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content.Headers.ContentLength = stream.Length;
来源:https://stackoverflow.com/questions/44925841/webapi-returns-corrupted-incomplete-file