WebAPI returns 损坏、不完整的文件
WebAPI returns corrupted, incomplete file
我想 return 来自 WebApi 端点的图像。这是我的方法:
[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");
}
}
很遗憾,下载的文件不完整。使用 Android 应用程序的消息是:
java.io.EOFException: source exhausted prematurely
问题很可能是您的 Android 客户端认为下载在实际结束之前就已经结束了。
要轻松解决此问题,您可以改用此方法,它会 return 一次整个文件(而不是流式传输):
result.Content = new ByteArrayContent(File.ReadAllBytes(path));
原来这是由压缩引起的,压缩是为该控制器中的所有响应设置的。在控制器的构造函数中设置了 GZip 编码:
HttpContext.Current.Response.AppendHeader("Content-Encoding", "gzip");
HttpContext.Current.Response.Filter = new GZipStream(HttpContext.Current.Response.Filter, CompressionMode.Compress);
为了解决这个问题,我将这些行添加到我的方法中
(就在 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;
此外,我正在设置内容类型和长度,如下所示:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content.Headers.ContentLength = stream.Length;
我想 return 来自 WebApi 端点的图像。这是我的方法:
[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");
}
}
很遗憾,下载的文件不完整。使用 Android 应用程序的消息是:
java.io.EOFException: source exhausted prematurely
问题很可能是您的 Android 客户端认为下载在实际结束之前就已经结束了。
要轻松解决此问题,您可以改用此方法,它会 return 一次整个文件(而不是流式传输):
result.Content = new ByteArrayContent(File.ReadAllBytes(path));
原来这是由压缩引起的,压缩是为该控制器中的所有响应设置的。在控制器的构造函数中设置了 GZip 编码:
HttpContext.Current.Response.AppendHeader("Content-Encoding", "gzip");
HttpContext.Current.Response.Filter = new GZipStream(HttpContext.Current.Response.Filter, CompressionMode.Compress);
为了解决这个问题,我将这些行添加到我的方法中
(就在 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;
此外,我正在设置内容类型和长度,如下所示:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content.Headers.ContentLength = stream.Length;