【问题标题】:Upload large file async without disposing it异步上传大文件而不释放它
【发布时间】:2020-05-12 02:48:41
【问题描述】:

我正在构建一个 .NET Core 3.1 WEB API,它将接收一个大文件(最大 500MB),如果它有效,则向客户端返回 200 响应,然后才将上传的文件上传到 Azure Blob容器。

我遇到的问题是,在我将响应返回给客户端后,请求/流正在被处理(我相信),它没有给我任何错误,也没有上传。

我尝试了一些替代方案,但都没有成功:

  • Task.Run()
  • 锁定流,
  • 将流复制到新变量中
  • 同步流,
  • 带有后台队列的托管服务

文件成功上传的唯一方法是我将文件保存在本地或强制用户等待,但如果可以的话,我宁愿不这样做。

有没有人知道我该如何做到这一点?


编辑:

我使用文件上传操作在数据库上创建一个资源(并返回带有文件上传操作 ID 的 202),并根据上传到 Azure Blob 存储的成功更新它的状态。

用户可以在不同的 API 端点上检查上传状态。

我只是想知道在返回响应后是否有办法真正持久化文件流或任何对象。

【问题讨论】:

  • 如果用户不等待,那么如果上传到cloid成功,你将如何与用户沟通?
  • 您似乎在做两件事:1) 从用户那里下载项目。如果成功/失败,让用户知道。 2) 上传到云端。对于 1,您可以让用户等待。 2是你自己的担心。因此 1 可以是 Web API。 2 必须是其他一些自行运行并获取文件并将它们发送到云的进程。由于您是客户,因此这些故障需要您处理。
  • 顺便说一句,在这种情况下,返回202 Accepted 可能更合适。
  • 另外,您无需继续尝试替代方案。即使 Task.Run 工作,这也是一个糟糕的解决方案。您只需要真正了解 Web 在请求/响应模型上的工作原理,然后尝试一下。无论如何,您需要像我之前建议的那样,有一个单独的过程来上传到云端。
  • 我已经编辑了原始帖子以使其更清晰。

标签: c# .net-core filestream


【解决方案1】:

如果浏览器提供了Expect: Continue 标头。然后,您可以在客户端发送任何文件数据之前根据提供的请求标头使请求失败。或者然后以 100 continue 响应并读取文件数据。

但是,如果您想保留该文件数据,则必须先将其复制到某个位置,然后才能将状态代码返回给客户端。进入内存、本地磁盘或将其一直流式传输到后端 blob 容器。这就是 HTTP 的工作原理。

【讨论】:

    【解决方案2】:

    你的问题是有一个基本问题....

    如果有效,则向客户端返回 200 响应,然后才上传 将文件上传到 Azure Blob 容器。

    在很多情况下,这会导致客户端获得 200 而您没有将其上传到博客容器,因此 200 是一个谎言。因此,您不应该这样做。所以,这个问题没有实际意义。

    最重要的是,您不能真正做到这一点,因为 asp.net 将释放您获得的文件,因为这就是 asp.net 的工作方式 - 变量是请求上下文的一部分,因此在它的末尾被释放。

    【讨论】:

    • 我根据调用向数据库(不是文件)添加资源,并将文件上传状态的数据库上传到 Azure blob 容器。因此 200 是有效的,因为我根据发送的请求在数据库中创建了一个资源。因此,有没有办法让 .net core(不是 asp.net)在使用文件时对其进行处理?
    • 首先,它是无效的,因为您没有上传文件,但您向客户端报告所有完成 - 如果后端在两者之间失败怎么办?这可能发生,坏消息。其次,正如我所说——不。文件资源归 WebApi 所有,一旦您返回它就不再有效。
    • 你是对的 - 200 无效。正如 devNull 建议的那样,我应该返回 202 而不是 200。
    【解决方案3】:

    文件成功上传的唯一方法是我将文件保存在本地或强制用户等待

    您可以将流复制到 MemoryStream,然后将其传递给后台进程进行上传。但它会占用大量内存,并且无法在应用程序重新启动后继续存在。

    将流复制到本地文件,并将其传递给后台进程,每个请求至少不会占用 500MB 内存,并且可以在应用程序重新启动后继续存在。

    【讨论】:

    • 谢谢大卫布朗,我想我必须这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多