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> GY6itug <httpRuntime executionTimeout="240" maxRequestLength="20480" /> GY6itug </system.web> |
若是在machine.config中对该值进行了修改,那么同时受到影响的就不只是这一个网站。ASP.NET之所以设计了这样的上限,就是为了避免潜 在的攻击。所以最好的方式是在某个特定目录中进行覆盖,而不是整个应用程序。web.config文件的格式非常灵活,因此实现这样的需求也不难:
web.config文件允许级联覆盖,所以很容易就能够实现这个要求。我们可以在某个文件夹中添加web.config文件,并书写上述配置,或者干脆在web.config文件中添加一个专门的<location />标签,也能达到同样的效果:
<location path="Upload">GY6itug <system.web>GY6itug <httpRuntime executionTimeout="110" maxRequestLength="20000" />GY6itug </system.web>GY6itug </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实现,在通过进度条给用户充分提示的同时,也让我们开发人员能够更好地控制文件大小以及上传过程中可能出现的异常。
下面是一些常见的组件:
- FileUploader.NET (MediaChase公司,$310以上)
- RadUpload (Telerik公司,$249)
- NeatUpload (免费,遵守LGPL协议)
文章建议,最好的解决方案是使用RIA,例如那些用ASP.NET和Silverlight编写的上传组件。
大多数情况下,我建议用给予Silverlight或Flash的上传组件来替代传统的FileUpload组件。这类组件不单单提供了更好的上传体验,也通常会比<input type="file">在页面上生成的文本框和按钮要漂亮一些。这个<input type="file">并不能够通过CSS添加样式,虽然总是有人尝试去寻找一些方法。
虽然目前并没有什么商业上传组件使用了Silverlight,不过我们可以找到一个示例程序演示了用Silverlight进行多文件上传的方法。
哪怕是如同文件上传一般微不足道的问题,我们都能够找到很多种不同的方法来解决。而最大的挑战在于分析各种不同做法的利弊,以及衡量用各个做法解决这个问题所要花费的时间和金钱。只有仔细分析计划之后,我们才能够找到最适合项目中使用的方法。