繁体   English   中英

多个异步文件上传与分块到 ASP.Net Web API

[英]Multiple Async File Uploads with chunking to ASP.Net Web API

我已经阅读了许多密切相关的问题,但没有一个完全符合这一点。 如果是重复的,请给我一个链接。

我正在使用 flowjs 库的 angular 版本进行 HTML5 文件上传( https://github.com/flowjs/ng-flow )。 这很好用,我能够以 1MB 的块同时上传多个文件。 有一个 ASP.Net Web API 文件 controller 接受这些并将它们保存在磁盘上。 虽然我可以完成这项工作,但我没有有效地完成它,并且想知道更好的方法。

首先,我在异步方法中使用了 MultipartFormDataStreamProvider,只要文件上传到单个块中,它就可以很好地工作。 然后我切换到只使用 FileStream 将文件写入磁盘。 只要块按顺序到达,这也有效,但当然,我不能依赖这一点。

接下来,为了看到它的工作,我将块写入单个文件流并在事后将它们组合起来,因此效率低下。 一个 1GB 的文件会生成一千个需要在上传完成后读取和重写的块。 我可以在 memory 中保存所有文件块并在它们全部上传后刷新它们,但我担心服务器会炸毁。

似乎应该有一个很好的异步解决方案来解决这个困境,但我不知道它是什么。 一种可能性可能是在写入当前块时使用async / await来组合先前的块。 另一个可能是使用Begin / EndInvoke创建一个单独的线程,以便独立于从HttpContext读取的线程处理磁盘上的文件操作,但这将依赖于ThreadPool并且我担心创建的线程将被过度终止当我的 MVC controller 返回时。 我可以创建一个完全独立于 ASP.Net 运行的FileWatcher ,但这会非常笨拙。

所以我的问题是,1)我已经缺少一个简单的解决方案了吗? (似乎应该有)和 2)如果没有,在 Web API 框架内解决此问题的最佳方法是什么?

谢谢,鲍勃

我不熟悉那种分块上传,但我相信这应该有效:

  • 当第一个块进入时,使用flowTotalSize 预分配文件
  • 每个文件都有一个SemaphoreSlim来序列化该文件的异步写入。
  • 每个块都将写入文件中自己的偏移量flowChunkSize * (flowChunkNumber - 1) )。

这不会处理上载意外终止的情况。 这种解决方案通常涉及分配/写入临时文件(带有特殊扩展名),然后在最后一个块到达后移动/重命名该文件。

不要忘记确保您的文件写入实际上是异步的

使用@Stephen Cleary的答案,以及这个帖子: https//github.com/flowjs/ng-flow/issues/41我能够制作一个ASP.NET Web Api实现并上传给那些仍然想知道这个问题的人作为@Herb Caudill

https://github.com/samhowes/NgFlowSample/tree/master

最初的答案是这个问题的真正答案,但我还没有足够的声誉来评论。 我没有使用SemaphoreSlim,而是启用了文件写共享。 但实际上是预先分配并确保通过计算偏移量将每个块写入正确的位置。

我将在以下网址为Flow示例做出贡献: https//github.com/flowjs/flow.js/tree/master/samples

这就是我所做的。 上传块并将这些块保存在服务器上,并保存数据库中块的位置及其顺序(不是它们进入的顺序,它们应该是文件中块的顺序)。

然后我引入了另一个端点来合并这些块。 由于这部分可能是一个漫长的过程,因此我使用消息传递服务在后台运行该过程。

在服务完成合并文件后,发送通知(或者您可以触发事件)。

同意,它不会解决必须保存所有这些块的问题,但是在合并完成后,我们可以从磁盘中删除它们。 然而,为了顺利上传,需要一些 IIS 配置。

这是我对这个老问题的两分钱。 现在大多数应用程序使用 azure 或 aws 进行存储。 但是,仍然分享我的想法,以防它帮助某人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM