C# 上传时验证大文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10445861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validating for large files upon Upload
提问by William Calleja
I am working with c# MVC 2 and ASP.NET. One of my forms includes a file input field which allows a use to select any file type which will then be converted into a blob and saved into the database. My problem is that whenever a user selects a file that exceeds a certain amoutn of Mb (about 8) I get a page error that says the following:
我正在使用 c# MVC 2 和 ASP.NET。我的一个表单包括一个文件输入字段,它允许用户选择任何文件类型,然后将其转换为 blob 并保存到数据库中。我的问题是,每当用户选择超过一定 Mb(大约 8)的文件时,我都会收到一个页面错误,内容如下:
The connection was reset
The connection to the server was reset while the page was loading.
I don't mind that there's an 8Mb limit to the files the users are uploading however I need to stop the current error from happening and display a proper validation message (preferably with the ModelState.AddModelError function). Can anybody help me? I can't seem to 'catch' the error before anything else happens in the page since it's happening before it arrives in the upload function within the controller.
我不介意用户上传的文件有 8Mb 的限制,但是我需要阻止当前错误的发生并显示正确的验证消息(最好使用 ModelState.AddModelError 函数)。有谁能够帮助我?我似乎无法在页面中发生任何其他事情之前“捕获”错误,因为它是在它到达控制器内的上传功能之前发生的。
采纳答案by Darin Dimitrov
One possibility is to write a custom validation attribute:
一种可能性是编写自定义验证属性:
public class MaxFileSizeAttribute : ValidationAttribute
{
private readonly int _maxFileSize;
public MaxFileSizeAttribute(int maxFileSize)
{
_maxFileSize = maxFileSize;
}
public override bool IsValid(object value)
{
var file = value as HttpPostedFileBase;
if (file == null)
{
return false;
}
return file.ContentLength <= _maxFileSize;
}
public override string FormatErrorMessage(string name)
{
return base.FormatErrorMessage(_maxFileSize.ToString());
}
}
and then you could have a view model:
然后你可以有一个视图模型:
public class MyViewModel
{
[Required]
[MaxFileSize(8 * 1024 * 1024, ErrorMessage = "Maximum allowed file size is {0} bytes")]
public HttpPostedFileBase File { get; set; }
}
controller:
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
// validation failed => redisplay the view
return View(model);
}
// the model is valid => we could process the file here
var fileName = Path.GetFileName(model.File.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
model.File.SaveAs(path);
return RedirectToAction("Success");
}
}
and a view:
和一个观点:
@model MyViewModel
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.TextBoxFor(x => x.File, new { type = "file" })
@Html.ValidationMessageFor(x => x.File)
<button type="submit">OK</button>
}
Now of course for this to work you will have to increase the maximum allowed upload file size in web.config to a sufficiently large value:
现在当然要让它工作,你必须将 web.config 中允许的最大上传文件大小增加到足够大的值:
<!-- 1GB (the value is in KB) -->
<httpRuntime maxRequestLength="1048576" />
and for IIS7:
对于 IIS7:
<system.webServer>
<security>
<requestFiltering>
<!-- 1GB (the value is in Bytes) -->
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
We could now bring our custom validation attribute a step further and enable client side validation to avoid wasting bandwidth. Of course verifying the file size before uploading is only possible with HTML5 File API. As a consequence only browsers that support this API will be able to take advantage of it.
我们现在可以将我们的自定义验证属性更进一步,并启用客户端验证以避免浪费带宽。当然,只有使用HTML5 File API才能在上传之前验证文件大小。因此,只有支持此 API 的浏览器才能利用它。
So the first step is to make our custom validation attribute implement the IClientValidatableinterface which will allow us to attach a custom adapter in javascript:
所以第一步是让我们的自定义验证属性实现IClientValidatable接口,这将允许我们在 javascript 中附加一个自定义适配器:
public class MaxFileSizeAttribute : ValidationAttribute, IClientValidatable
{
private readonly int _maxFileSize;
public MaxFileSizeAttribute(int maxFileSize)
{
_maxFileSize = maxFileSize;
}
public override bool IsValid(object value)
{
var file = value as HttpPostedFileBase;
if (file == null)
{
return false;
}
return file.ContentLength <= _maxFileSize;
}
public override string FormatErrorMessage(string name)
{
return base.FormatErrorMessage(_maxFileSize.ToString());
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(_maxFileSize.ToString()),
ValidationType = "filesize"
};
rule.ValidationParameters["maxsize"] = _maxFileSize;
yield return rule;
}
}
and all that's left is configure the custom adapter:
剩下的就是配置自定义适配器:
jQuery.validator.unobtrusive.adapters.add(
'filesize', [ 'maxsize' ], function (options) {
options.rules['filesize'] = options.params;
if (options.message) {
options.messages['filesize'] = options.message;
}
}
);
jQuery.validator.addMethod('filesize', function (value, element, params) {
if (element.files.length < 1) {
// No files selected
return true;
}
if (!element.files || !element.files[0].size) {
// This browser doesn't support the HTML5 API
return true;
}
return element.files[0].size < params.maxsize;
}, '');
回答by Dhwanil Shah
I googled around a bit and came up with the following two URLs which seem to suggest that this problem or exception is best handled at Application's Error event in Global.asax.
我用谷歌搜索了一下,找到了以下两个 URL,它们似乎表明这个问题或异常最好在 Global.asax 中的应用程序错误事件中处理。
回答by Eugeniu Torica
You can increase request max length for certain urls in web.config:
您可以在 web.config 中增加某些 url 的请求最大长度:
<location path="fileupload">
<system.web>
<httpRuntime executionTimeout="600" maxRequestLength="10485760" />
</system.web>
</location>

