正在上传大文件

时间:2012-08-02 14:35:57

标签: asp.net webforms pagemethods web-farm

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

他的公司生产3D模型(使用3D打印机)。该网站目前正在开发中,但可以找到here。我是第一个承认代码有点匆忙和黑客入侵的人,但我的朋友对他到目前为止所做的事情非常满意。

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

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

这适用于小型测试文件但不提供上传进度的任何指示。因此,我尝试使用Sunasara Imdadhusen在其code project article中开发的想法来改进我的解决方案。我的上传代码如下所示:

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是对作为会话变量存储的类的引用,并且是通过PageMethod从setInterval(...)中运行的javascript函数(在上载过程中)访问的:

[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园或Web场上无法正常工作”,并且还说它可以在Web场上运行“指定相同的随机每个服务器的Web.config部分中的32位十六进制的decryptionKey属性“。但我认为我无法访问123-Reg的服务器配置文件(?)。

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

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


编辑:到目前为止的故事......仍然在努力解决这个问题。

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

到目前为止,我一直在测试IE9,我刚刚尝试使用Chrome浏览器,我注意到了一件有趣的事情。在点击上传按钮之后但在页面刷新之前,Chrome在左下方显示了一个上传%完成对话框。这一比例达到100%,然后我的控件开始显示一些操作,然后整个页面再次开始挂起。

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

这是否意味着在等待上传的痛苦部分(实际发生在客户端和缓冲区之间)之后我的任务正在启动?如果是这种情况,那么通过将文件发送到Dropbox对话来让它更痛苦是没有意义的吗?我的进度条是跟踪错误位的进度?

(今天我要检查我的代码的错误处理,因为我感觉它挂​​起的原因是因为它没有正确地从异常中恢复)。这当然感觉我通过这种方式学到很多东西。

1 个答案:

答案 0 :(得分:1)

这可能有点矫枉过正,但你可以考虑使用BluImp的jQuery文件上传工具(Demo site here: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的文件,并且发现它非常灵活!