【问题标题】:Return file from ASP.NET 5 Web API从 ASP.NET 5 Web API 返回文件
【发布时间】:2016-04-23 18:10:21
【问题描述】:

我之前的问题:How to return file from ASP.net 5 web api

我正在尝试返回一个文件作为来自 Web API POST 请求的响应。

我正在使用 dnx451 框架和 rc1-final 构建。控制器方法:

[HttpPost("")]
public ActionResult Post([FromBody]DocumentViewModel vm)
{
    try
    {
        if (ModelState.IsValid)
        {

            var Document = _repository.GetDocumentByGuid(vm.DocumentGuid, User.Identity.Name);
            var Params = Helper.ClientInputToRealValues(vm.Parameters, Document.DataFields);
            var file = Helper.GeneratePdf(Helper.InsertValues(Params, Document.Content));
            FileStream stream = new FileStream(file,FileMode.Open);

            return File(stream, "application/pdf", "test.pdf");

        }

    }
    catch (Exception ex)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return null;
    }
    Response.StatusCode = (int)HttpStatusCode.BadRequest;
    return null;

}

结果我得到了一个名为“response”的文件。保存为pdf后,我尝试打开它,它说它已损坏。希望您能够帮助我。我正在使用 Postman 作为测试客户端。

谢谢

【问题讨论】:

  • 调试时,代码是否到达return File() 行?响应中收到的内容和标头是什么?
  • 您的Helper.GeneratePdf() 线路是否正常工作? file 的值是多少?可以打开文件吗?您是否在将生成的文件发送回浏览器之前检查了它?
  • 是的,pdf已经生成,我可以从文件资源管理器打开生成的pdf文件,就可以了。

标签: c# asp.net-web-api asp.net-core


【解决方案1】:

考虑使用FileStreamResult 操作结果可能会更好。

这样做的好处是不需要将整个文件内容保存在内存中,这取决于文件的大小、流量级别等,很容易导致规模问题。

类似这样的:

[HttpGet]
public FileStreamResult DownloadFile()
{
    var Document = _repository.GetDocumentByGuid(vm.DocumentGuid, User.Identity.Name);
    var Params = Helper.ClientInputToRealValues(vm.Parameters, Document.DataFields);
    var file = Helper.GeneratePdf(Helper.InsertValues(Params, Document.Content));
    var stream = new FileStream(file,FileMode.Open);
    return new FileStreamResult(stream, "application/pdf")
    {
        FileDownloadName = "test.pdf"
    };
}

【讨论】:

  • 不是来自 MVC 的 FileStreamResult 吗?
  • 这需要导入 System.Web.Mvc,这将破坏 WebAPI 控制器中的所有其他内容。问题是关于 WebAPI。
【解决方案2】:

我刚刚遇到这个问题并找到了解决方案。只要您有文件的绝对路径,那么您就可以返回一个PhysicalFileResult 并在Response 上显式设置Content-Disposition 标头,如下所示:

[HttpGet("{key}")]
public IActionResult Get(string key)
{
    var file = _files.GetPath(key);

    var result = PhysicalFile(file.Path, "text/text");

    Response.Headers["Content-Disposition"] = new ContentDispositionHeaderValue("attachment")
    {
        FileName = file.Name
    }.ToString();

    return result;
}

使用PhysicalFile还有一个好处是所有的异步字节流等都由框架处理。

【讨论】:

    【解决方案3】:

    请在另一篇文章中查看我的回答:Return file as response

    作为参考,我认为这符合您的需求:

    public FileResult TestDownload()
    {
        HttpContext.Response.ContentType = "application/pdf";
        FileContentResult result = new FileContentResult(System.IO.File.ReadAllBytes("YOUR PATH TO PDF"), "application/pdf")
        {
            FileDownloadName = "test.pdf"
        };
    
        return result;                                
    }
    

    【讨论】:

    • 结果还是一样。响应返回名为“响应”的文件。如果我将它重命名为 somthing.pdf 并尝试打开它 - 它仍然损坏。
    • 我已经使用本地 pdf 在本地测试了该代码,并且文件已正确下载并且可以打开它。 pdf路径是您机器的本地路径,还是您动态生成它?在我提到“您的 PDF 路径”的地方,您还必须包含扩展名。
    • 基本上我正在创建它,但 atm 我正在使用本地文件进行测试。是的 .pdf 包括在内。我认为这可能是 PostMan 的问题。
    • 很可能,要确认代码适用于您的 PDF,您可以创建一个新的 MVC 项目,然后将该方法添加到为您生成的 HomeController.cs 中。这就是我在发布之前所做的测试。然后你可以从那里找出罪魁祸首:)
    • FileResult 和 FileContentResult 是 Mvc 类,不是 Webapi
    猜你喜欢
    • 2016-04-23
    • 2018-07-17
    • 2021-09-24
    • 2019-01-17
    • 2016-03-16
    • 2016-07-11
    • 2016-12-17
    • 1970-01-01
    • 2015-01-05
    相关资源
    最近更新 更多