WebAPI returns damaged, incomplete file

I want to return an image from a 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");
    }
}

      

Sorry, the downloaded file is incomplete. Android app consumption message:

java.io.EOFException: Source exhausted prematurely

+3


source to share


2 answers


It turns out this was caused by a compression that was set for all responses in that controller. GZip encoding is set in the controller of the controller:

HttpContext.Current.Response.AppendHeader("Content-Encoding", "gzip");
HttpContext.Current.Response.Filter = new GZipStream(HttpContext.Current.Response.Filter, CompressionMode.Compress);

      

To solve this problem, I added these lines to my method (right after the start of the block try

):



// 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 am setting the content type and length like this:

result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content.Headers.ContentLength = stream.Length;

      

0


source


The problem is that your Android client thinks the download is complete before it actually does. To fix this easily, you can use this method instead, which will return the entire file at once (instead of streaming it):



result.Content = new ByteArrayContent(File.ReadAllBytes(path));

      

0


source







All Articles