【问题标题】:Using Azure Function (.NET Core) to Download a file使用 Azure Function (.NET Core) 下载文件
【发布时间】:2019-03-13 07:55:58
【问题描述】:

我使用 .NET Core 创建并使用 HTTP 触发的 Azure 函数 (v2),希望我可以执行该函数,同时在请求正文中传递一些信息,然后让该函数在浏览器中返回/下载文件。不幸的是,我正在努力让它发挥作用。

下面是sn-p的代码

public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
    string csv;

    //Do some stuff to create a csv

    byte[] filebytes = Encoding.UTF8.GetBytes(csv);

    req.HttpContext.Response.Headers.Add("content-disposition", "attachment;filename=Export.csv");
    req.HttpContext.Response.ContentType = "application/octet-stream";

    return (ActionResult)new OkObjectResult(filebytes);
}

当我使用 Postman 发帖时,请求被接受,但响应为 406“不可接受”,并且日志状态中的输出

"Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector[1] 没有找到内容类型“application/octet-stream”的输出格式化程序来写入响应。”

我尝试了多种内容类型,包括 text/plain 和 text/csv,都对输出格式给出了相同的响应。

如果我删除或注释掉 ContentType,请求会处理并返回 200,但文件字节会在响应正文中返回,而不是在浏览器中下载。

【问题讨论】:

  • return new FileContentResult(fileBytes, "text/csv") { FileDownloadName = "Export.csv" }; 无需手动更改响应。
  • 你的函数不应该直接返回文件。重点是卸载工作并在后台处理它。如果您的操作必须等待函数创建文件,您不妨改为在操作中完成所有操作,并放弃 Azure 函数的额外开销。假设它是在后台处理的,该函数应该以某种方式通过消息队列、SignalR 等通知您的应用程序已完成。然后,应用程序可以相应地通知客户端并推送下载或提供客户端可以下载的链接拿来。
  • 是的,绝对是 Chris 所说的。从 Azure 函数返回文件也可能导致非常不可预测的成本,因为对于 Internet 连接速度快的用户,相同的函数可能运行 1 秒,而对于连接速度较慢的用户,则可能运行 30 秒。 Azure 函数应该主要是计算或后台任务,如果你返回文件,它们应该非常小(我会说在 1-2 kb 以下,比如一个小的 json 响应等),以避免在许多慢速连接时你的成本飙升。跨度>
  • 处理文件时,您应该将结果文件存储到 azure 文件或 blob 存储中,并使该链接可供调用者使用,以便他们可以从那里直接访问它
  • 感谢@AndyJ 完美运行!正如我在发布的答案中提到的那样,这是针对项目的一小部分,并且函数本身并不经常运行,返回非常少量的数据并在一两秒内运行,这就是我不同意的原因cmets中发布的其他解决方案。此外,我们将在现有的应用服务中托管它,因此与消费模型相关的成本不适用。感谢您的意见!

标签: c# asp.net-core .net-core azure-functions azure-functions-runtime


【解决方案1】:

为此,您需要一个 FileContentResult:

public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
    string csv;

    //Do some stuff to create a csv

    byte[] filebytes = Encoding.UTF8.GetBytes(csv);

    return new FileContentResult(filebytes, "application/octet-stream") {
        FileDownloadName = "Export.csv"
    };
}

虽然 cmets 正确指出,理想的解决方案是在 HTTP 函数中异步启动处理,返回 202 Accepted 响应,将结果保存到 blob 存储,让客户端在开始 blob 下载之前等待处理完成然后在下载 blob 后将其删除,当前的 Azure Functions 定价仅为 0.000016 美元/GB-s,因此除非您的流量非常高,否则您可能会发现这太复杂了。

【讨论】:

  • 谢谢! 1 小行代码一直支撑着我!这是针对项目的一小部分,并且函数本身不经常运行,返回非常少量的数据并在一两秒钟内运行,这就是为什么我不同意 cmets 中发布的其他解决方案的原因。此外,我们将在现有的应用服务中托管它,因此与消费模型相关的成本不适用。再次感谢!
  • 万一其他人来这里寻找如何将流作为文件返回,您可以使用 FileStreamResult:return new FileStreamResult(memoryStream, "application/octet-stream") { FileDownloadName = "Export.csv" };
  • 这不适用于 .net5。你知道如何使用吗?
猜你喜欢
  • 1970-01-01
  • 2019-06-27
  • 2019-02-10
  • 2022-12-24
  • 2017-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多