2012-08-02 117 views
3

我是一名业余ASP.net开发人员,负责我的第一份工作(朋友网站)。 ASP.net v4.0,使用VS2010。上传大文件

他的公司生产3D模型(使用3D打印机)。该网站目前正在开发中,但可以找到here。我会第一个承认代码有点匆匆入侵,但我的朋友对他到目前为止很满意。

其中一个要求是他的客户需要能够上传他们的模型设计文件,每个文件可能高达100 MB(或者更多)。我努力让这个工作正常。

我开始使用内置的<asp:FileUpload ID="FileUpload1" runat="server" />标签和一个动画gif图像,类似于Joe Stagner's tutorial中描述的想法 - 感谢乔,我非常喜欢您的演示文稿。

这对一个小测试文件工作正常,但没有给出任何上传进度的迹象。所以我试图用他的code project article中Sunasara Imdadhusen开发的想法改进我的解决方案。我上传的代码如下所示:

Task t = Task.Factory.StartNew(() => 
{ 
    byte[] buffer = new byte[UPLOAD_BUFFER_BYTE_SIZE]; 

    // Upload the file in chunks so that we can measure how long it is taking. 
    using (FileStream fs = new FileStream(Path.Combine(newQuotePath, filename), FileMode.Create)) 
    { 
     DateTime stopwatch = DateTime.Now; 

     while (stats.Uploaded < stats.TotalSize) 
     { 
      int bytecount = postedFile.InputStream.Read(buffer, 0, UPLOAD_BUFFER_BYTE_SIZE); 
      fs.Write(buffer, 0, bytecount); 

      stats.Uploaded += bytecount; 

      double dRate = UPLOAD_BUFFER_BYTE_SIZE/Math.Abs((DateTime.Now - stopwatch).TotalSeconds); 
      stats.Rate = (int)(Math.Min(dRate, int.MaxValue)); 

      // Sleep is for debugging only! 
      //System.Threading.Thread.Sleep(2000); 

      stopwatch = DateTime.Now; 
     } 
    } 
}, TaskCreationOptions.LongRunning); 

哪里stats是存储为一个会话变量类的引用,并从一个JavaScript函数在setInterval(...)运行(而上传正在发生)的访问该PageMethod:

[System.Web.Services.WebMethod] 
[System.Web.Script.Services.ScriptMethod] 
public static UploadStatus GetFileUploadStatus() 
{ 
    UploadStatus stats = (UploadStatus)HttpContext.Current.Session["UploadFileStatus"]; 

    if ((stats != null) && (stats.IsReady)) 
    { 
     return stats; 
    } 
    else 
    { 
     return null; 
    } 
} 

这在我的本地机器上工作(使用线程睡眠来减慢上传速度)。所以我将它发布到我们的主机123-Reg,它没有按预期工作。上传开始时,动画gif开始显示,但进度条未开始移动。文件输入控件和提交按钮(在IFrame中)只要上传开始就应该被禁用,使用时间将被禁用。然后网页就挂在那里。等了一段时间后,我点击了页面刷新按钮。当页面刷新时,表明我的测试文件已成功上传。我试了一个16 KB的文件和一个1.6 MB的文件。

因为这在我的本地机器上工作,我怀疑这是因为我们的网站主机(123-Reg)正在使用网络农场。

无论如何,我认为这会很容易,但事实并非如此,所以我找了一些开源上传进度条。我看了一下NeatUpload,但它说“默认情况下,NeatUpload在网上花园或网上农场不能正常工作”,并且它也说让它在Web场上工作“指定相同的随机32-每个服务器的Web.config部分中的数字解密密钥属性“。但我不认为我有权访问123-Reg的服务器配置文件(?)。

我的朋友建议,也许我们可以使用服务,如dropbox,但我看了一下,我不知道如何将其添加到我们的网站。这可能是一个不错的选择,因为它们可能针对上传进行了优化。

任何意见或建议将非常感谢 - 谢谢。


编辑:到目前为止的故事......仍然与此挣扎。

我仔细研究了使用Dropbox(以及其他云存储提供商,如SkyDrive等)。似乎这些服务是围绕提供与个人用户存储交互的应用程序而设计的。我希望所有用户能够将文件上传到我的Dropbox文件夹,但不共享(客户不应访问其他客户的设计文件)。无论如何,我继续,设置一个Dropbox帐户,安装Sharpbox SDK并重新编程我的上传代码(任务操作中的位)。这似乎在我的本地计算机上工作正常,但速度稍慢,因为它正在上传到保管箱服务器(我不需要Thread.Sleep)。我将网站发布到123-Reg服务器,并得到了与以前类似的无法使用的体验。

到目前为止,我一直在IE9上进行测试,并且我只是想用Chrome浏览器进行测试,而且我注意到了一个有趣的事情。只需点击上传按钮,但在刷新页面之前,Chrome在左下角显示一个上传%完成对话框。这运行到100%,然后我的控件在整个页面再次挂起之前开始显示一些操作。

根据MSDN的HttpPostedFile: “默认情况下,所有的请求,包括表单字段和上传文件,大于256 KB的缓存到磁盘”

那么,这是否意味着以后我的工作正在启动等待上传的痛苦部分(实际上发生在客户端和缓冲区之间)?如果是这种情况,那么通过将文件发送到Dropbox的方式使它更加痛苦是没有意义的?我的进度条正在跟踪错误的进度? (今天我要检查我的代码的错误处理,因为我有一种感觉,它挂起的原因是因为它没有正确地从异常恢复)。这当然让我感觉我正在学习很多东西。

+0

使用云代替,如果它不贵,或者购买hostin自己的服务器。似乎托管提供商限制了请求大小。 – 2012-08-02 14:47:35

+0

根据[serialseb的帖子](http://stackoverflow.com/a/1156906/340045):只要您使用HttpRequest.InputStream,Asp.net就会始终加载整个请求内容,所以我想这可能会导致一些问题对我来说。 – Ben 2012-08-04 11:43:40

回答

1

这可能有点矫枉过正,但您可以考虑使用BluImp的jQuery文件上传工具(演示站点在这里:http://blueimp.github.com/jQuery-File-Upload/) - 名为Max Pavlov的开发人员修改了原始版本(最初用于非dotnet技术) MVC 3.

它可以在这里找到git hub https://github.com/maxpavlov/jQuery-File-Upload.MVC3。我已经在MVC 3和MVC 4 Beta中成功实现了这一点。为了在MVC 4中有效地工作,唯一必须做的是删除一些ClientDependancy(这是一个处理JS和CSS文件的捆绑和缩小的DLL)代码,因为它复制了MVC 4中的功能,而不是MVC中的功能3.此外,我在GitHub上向wiki上添加了一些页面,描述了我做了什么,尽管它没有完成。如果你决定走这条路,我可以用我最近的发现来更新一些细节。我迄今为止关于MVC 4集成的笔记可以在这里找到https://github.com/maxpavlov/jQuery-File-Upload.MVC3/wiki/MVC-4---EnableDefaultBundles

顺便说一下,我设法使用这个工具上传大约2Gb的文件,并发现它非常灵活!