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

bob*_*bob 9 c# asp.net multithreading asynchronous asp.net-web-api

我已经阅读了许多密切相关的问题,但没有一个能够完全达到这个问题.如果是重复,请发给我一个链接.

我正在使用一个有角度版本的flowjs库来进行HTML5文件上传(https://github.com/flowjs/ng-flow).这非常有效,我能够以1MB的块同时上传多个文件.有一个ASP.Net Web API文件控制器接受这些并将它们保存在磁盘上.虽然我可以做到这一点,但我并没有有效地做到这一点,并且想要了解更好的方法.

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

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

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

所以我的问题是,1)是否有一个我想念的简单解决方案?(似乎应该有)和2)如果没有,在Web API框架内解决这个问题的最佳方法是什么?

谢谢,鲍勃

Ste*_*ary 9

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

  • 使用flowTotalSize预先分配的文件,当第一块用武之地.
  • SemaphoreSlim每个文件都有一个序列化该文件的异步写入.
  • 每个块都将写入flowChunkSize * (flowChunkNumber - 1)文件中自己的offset().

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

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

  • @Bob - 试着在这里做同样的事情.您的成功解决方案是否公开?可以使用一些示例代码来帮助我开始. (3认同)

Sam*_*Sam 7

使用@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