我们必须根据请求中指定的HttpRange
发送文件的一部分。在.Net core中,我们可以返回从FileResult
继承的任何对象,并且此类具有用于指定是否必须启用范围处理的属性:
/// <summary>
/// Gets or sets the value that enables range processing for the <see cref="FileResult"/>.
/// </summary>
public bool EnableRangeProcessing { get; set; }
我们可以返回那些对象,框架将自动处理请求的“ http范围”值。到目前为止更好。但是,他们有意识地决定在一个请求中不支持多个字节范围,在这种情况下,整个文件内容将作为响应发送。 (here是我对此问题的SO问题的链接)
在我们的例子中,客户希望在一个请求中发送多个字节范围。
因此,我有两个选择。创建支持单个范围和多个范围的新操作结果类型。或者使用Microsoft开发的Microsoft.AspNetCore.Mvc.WebApiCompatShim
软件包,该软件包在ASP.NET Core MVC中提供与ASP.NET Web API 2的兼容性,以简化现有Web API实现的迁移。
我已经创建了一些自定义类型来支持多个范围,但是必须对其进行重构,测试。 这就是为什么我认为第二种方法与这种情况更为相关。
因此,这是步骤。首先,我安装了该软件包。然后添加对AddWebApiConventions
的呼叫。这将连接HttpResponseMessageOutputFormatter
来帮助并提示Json
序列化程序正确执行其序列化魔术。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddWebApiConventions();
}
然后刚刚创建了新的ApiController
,它基于ByteRangeStreamContent
创建了响应:
public class FileController : ApiController
{
[HttpGet]
[HttpHead]
[Route("download")]
public ResponseMessageResult Download(string filePath)
{
var response = Request.CreateResponse(HttpStatusCode.PartialContent);
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
response.Content = new ByteRangeStreamContent(fileStream, Request.Headers.Range, MediaTypeNames.Application.Octet);
return ResponseMessage(response);
}
}
该端点可以在.Net中执行单个和多个http范围请求。但是,在.net内核中,它再次仅支持单字节范围响应。
假设我的文件包含以下内容:
ABCDFGHIJKLMNOPQRSYUVWXYZ
对于单字节范围请求,响应为:
curl -H Range:bytes=1-5 http://localhost:55348/File/download?filePath=D:\Request.txt -i
ABCDF
但是,如果有多个字节范围的请求,则会奇怪地返回第一个范围的完整内容:
curl -H Range:bytes=1-5,6-8 http://localhost:55348/File/download?filePath=D:\Request.txt -i
--51239b4a-9749-481f-a353-6cad668fb7dc
Content-Type: application/octet-stream
Content-Range: bytes 1-5/25
ABCDFGHIJKLMNOPQRSYUVWXYZ -- As you see full content is returned instead of `ABCDF`
--51239b4a-9749-481f-a353-6cad668fb7dc
Content-Type: application/octet-stream
Content-Range: bytes 6-8/25
不明白为什么它不能在.net Core中适当地创建响应。