我正在使用ASP.NET Core 2.1 ActionResult
[HttpGet]
public ActionResult<FileResult> Download()
{
var someBinaryFile = "somebinaryfilepath";
return File(new FileStream(firstExe, FileMode.Open, FileAccess.Read, FileShare.Read), System.Net.Mime.MediaTypeNames.Application.Octet, true);
}
但是它返回不完整的json而不是开始下载文件:
{"fileStream":{"handle":{"value":2676},"canRead":true,"canWrite":false,"safeFileHandle":
{"isInvalid":false,"isClosed":false},"name":"somebinaryfilepath","isAsync":false,"length":952320,"position":0,"canSeek":true,"canTimeout":false
Chrome devtools使用工具提示“ net :: ERR_SPDY_PROTOCOL_ERROR”将请求状态指示为“(失败)”
如果我更改代码以使其返回FileContentResult,则状态变为“ 200 ok”,但仍然写入json而不是文件下载:
{"fileContents": "somebinaryfilecontent","contentType":"application/octet-stream","fileDownloadName":"","lastModified":null,"entityTag":null,"enableRangeProcessing":true}
如果我将方法签名更改为
public FileResult Download()
或者
public IActionResult Download()
然后从两个FileResult实现开始下载文件。
如何使用ActionResult
答案 0 :(得分:6)
使用ActionResult<T>
时,这种情况下的T
是您要返回的specific type。默认情况下,如直接在问题中说明的那样,当直接从操作或使用ActionResult<T>
从操作返回时,此类型将序列化为JSON。
在您的示例中,您根本不返回任何特定类型,您将想要使用IActionResult
(根据您的问题,您已经看到过),如下所示:
[HttpGet]
public IActionResult Download()
{
...
}
您也可以使用ActionResult
,FileResult
或FileStreamResult
,但首选IActionResult
。
以下是为什么的解释,我认为这首先就发生了。
ActionResult<T>
包含两个隐式运算符:
public static implicit operator ActionResult<TValue>(TValue value)
{
return new ActionResult<TValue>(value);
}
public static implicit operator ActionResult<TValue>(ActionResult result)
{
return new ActionResult<TValue>(result);
}
在您的示例中,当返回FileStreamResult
时,可以使用这两个隐式运算符。一个以 any 类型(TValue
)操作,另一个以ActionResult
操作。我希望C#编译器选择第一个版本,因为TValue
(FileResult
)是FileStreamResult
(您的实际返回值)的更好匹配。 / p>
C# spec下的“ 11.5.4用户定义的隐式转换”部分对此进行了介绍。具体来说,我认为这是适用的说明(我在这里不是专家):
找到U中最特定的运算符源类型SX:
- 如果S存在并且U中的任何运算符都从S转换,则SX为S。
- 否则,SX是U中运算符的源类型的组合集中的被最广泛使用的类型。如果找不到恰好一个被最被广泛使用的类型,则转换是模棱两可的,并且会发生编译时错误。 / li>
在这种情况下,FileResult
是最具体的源类型(比ActionResult
更具体)。