ActionResult <fileresult>不能按预期工作

时间:2018-09-24 07:12:17

标签: c# asp.net-core asp.net-core-2.1

我正在使用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 下载文件?我是否缺少某些东西,或者确实是某种错误?

1 个答案:

答案 0 :(得分:6)

使用ActionResult<T>时,这种情况下的T是您要返回的specific type。默认情况下,如直接在问题中说明的那样,当直接从操作或使用ActionResult<T>从操作返回时,此类型将序列化为JSON。

在您的示例中,您根本不返回任何特定类型,您将想要使用IActionResult(根据您的问题,您已经看到过),如下所示:

[HttpGet]
public IActionResult Download()
{
    ...
}

您也可以使用ActionResultFileResultFileStreamResult,但首选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#编译器选择第一个版本,因为TValueFileResult)是FileStreamResult(您的实际返回值)的更好匹配。 / p>

C# spec下的“ 11.5.4用户定义的隐式转换”部分对此进行了介绍。具体来说,我认为这是适用的说明(我在这里不是专家):

  

找到U中最特定的运算符源类型SX:

     
      
  • 如果S存在并且U中的任何运算符都从S转换,则SX为S。
  •   
  • 否则,SX是U中运算符的源类型的组合集中的被最广泛使用的类型。如果找不到恰好一个被最被广泛使用的类型,则转换是模棱两可的,并且会发生编译时错误。 / li>   

在这种情况下,FileResult最具体的源类型(比ActionResult更具体)。