我是一名业余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的方式使它更加痛苦是没有意义的?我的进度条正在跟踪错误的进度? (今天我要检查我的代码的错误处理,因为我有一种感觉,它挂起的原因是因为它没有正确地从异常恢复)。这当然让我感觉我正在学习很多东西。
使用云代替,如果它不贵,或者购买hostin自己的服务器。似乎托管提供商限制了请求大小。 – 2012-08-02 14:47:35
根据[serialseb的帖子](http://stackoverflow.com/a/1156906/340045):只要您使用HttpRequest.InputStream,Asp.net就会始终加载整个请求内容,所以我想这可能会导致一些问题对我来说。 – Ben 2012-08-04 11:43:40