在 ASP.NET 中处理大文件上传

阅读数:25754 2008 年 1 月 28 日

话题:.NET微软最佳实践语言 & 开发

使用过 ASP.NET 的开发者都知道,FileUpload 控件是一把双刃剑——既可能成为我们的救世主,也能变成我们的敌人。其中一个很常见的问题就是如何处理超过 4MB 的大文件上传。

微软的 ASP.NET MVP Jon Galloway最近发表了一篇文章,其中讨论了 FileUpload 控件的种种使用技巧。了解了这些之后,我们即可在理论上处理任何大小的文件上传。

允许大文件上传

Jon 提到,使用FileUpload控件进行文件上传是一件非常有技巧性的事情。开发者应该了解的是,之所以默认的文件大小上限为 4MB,并不是因为当时的设计人员灵光一现,而是为了避免潜在 DOS 攻击危险。

若是攻击者提交了一个或多个大文件,往往会让服务器不堪重负。若是用户上传的文件大于 4MB,将会得到“Maximum request length exceeded.”异常信息。

想增加这个尺寸的上限并没有什么难度,不过开发者需要知道怎样做才是最好的方法。默认的 4MB 设定于系统的 machine.config 文件中,不过我们在 web.config 中即可覆盖该值。

例如,若想将上传文件的上限提高至 20MB,我们只需要这样修改:

<system.web>

<httpRuntime executionTimeout="240" maxRequestLength="20480" />

</system.web>

若是在 machine.config 中对该值进行了修改,那么同时受到影响的就不只是这一个网站。ASP.NET 之所以设计了这样的上限,就是为了避免潜 在的攻击。所以最好的方式是在某个特定目录中进行覆盖,而不是整个应用程序。web.config 文件的格式非常灵活,因此实现这样的需求也不难:

web.config 文件允许级联覆盖,所以很容易就能够实现这个要求。我们可以在某个文件夹中添加 web.config 文件,并书写上述配置,或者干脆在 web.config 文件中添加一个专门的 <location /> 标签,也能达到同样的效果:

<location path="Upload">

<system.web>

<httpRuntime executionTimeout="110" maxRequestLength="20000" />

</system.web>

</location>

对于允许大文件上传来说,改变默认的上传文件大小限制仅仅是我们要做的第一步。一篇名为文件上传的不为人知一面的文章揭示了更多有关与 IIS 配合完成文件上传的细节。

若是上传的文件太大的话,往往会出现一些很有意思的情况。无论maxRequestLength 在中设置成什么,IIS 都会不假思索地接受,但随后在 ASP.NET 检查时就会抛出异常。

这篇文章还提到:

当然很容易就可以捕获到这个异常,不过这并不是我们所期待的。还有一种方法是覆写 Page.OnError 方法,并通过检查在发生 HttpException 异常时 HTTP 响应代码是否为 400 来判断,不过这也不够完美。

给用户充分提示

一个让用户很反感的做法就是误导用户,而且在 Web 应用程序执行操作时也不给用户任何提示。文件尺寸的限制写在 web.config 中,所以将一段提示文字放在 web.config 中也就变成了件非常自然的事。

最好的做法就是在运行时读取 web.config 中的 httpRuntime 节,并转化为 HttpRuntimeSection 对象。非常简单:

System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration("~");

HttpRuntimeSection section = config.GetSection("system.web/httpRuntime") as HttpRuntimeSection;

double maxFileSize = Math.Round(section.MaxRequestLength / 1024.0, 1);

FileSizeLimit.Text = string.Format("Make sure your file is under {0:0.#} MB.", maxFileSize);

这个解决方案清晰易懂,也没有什么冗繁的代码。

更好的解决方案

还有一些商用的解决方案供我们选择。这些解决方案通过 HttpHandler 实现,在通过进度条给用户充分提示的同时,也让我们开发人员能够更好地控制文件大小以及上传过程中可能出现的异常。

下面是一些常见的组件:

文章建议,最好的解决方案是使用RIA,例如那些用 ASP.NET 和Silverlight编写的上传组件。

大多数情况下,我建议用给予 Silverlight 或 Flash 的上传组件来替代传统的 FileUpload 组件。这类组件不单单提供了更好的上传体验,也通常会比 <input type="file"> 在页面上生成的文本框和按钮要漂亮一些。这个 <input type="file"> 并不能够通过 CSS 添加样式,虽然总是有人尝试去寻找一些方法

虽然目前并没有什么商业上传组件使用了 Silverlight,不过我们可以找到一个示例程序演示了用 Silverlight 进行多文件上传的方法

哪怕是如同文件上传一般微不足道的问题,我们都能够找到很多种不同的方法来解决。而最大的挑战在于分析各种不同做法的利弊,以及衡量用各个做法解决这个问题所要花费的时间和金钱。只有仔细分析计划之后,我们才能够找到最适合项目中使用的方法。



查看英文原文:Handling Large File Uploads in ASP.NET