我正在使用c#MVC 2和ASP.NET。我的一个表单包括一个文件输入字段,允许用户选择任何文件类型,然后将其转换为blob并保存到数据库中。我的问题是,每当用户选择超过某个Mb(约8)的文件时,我会收到一个页面错误,其中包含以下内容:
The connection was reset
The connection to the server was reset while the page was loading.
我不介意用户上传的文件有8Mb的限制但是我需要停止当前错误的发生并显示正确的验证消息(最好使用ModelState.AddModelError函数)。有谁能够帮我?在页面中发生任何其他事情之前,我似乎无法“捕获”错误,因为它在控制器内的上传功能到达之前就已经发生了。
答案 0 :(得分:69)
一种可能性是编写自定义验证属性:
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());
}
}
然后你可以有一个视图模型:
public class MyViewModel
{
[Required]
[MaxFileSize(8 * 1024 * 1024, ErrorMessage = "Maximum allowed file size is {0} bytes")]
public HttpPostedFileBase File { get; set; }
}
控制器:
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");
}
}
和观点:
@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>
}
当然,为了实现这一点,您必须将web.config中允许的最大上传文件大小增加到足够大的值:
<!-- 1GB (the value is in KB) -->
<httpRuntime maxRequestLength="1048576" />
和IIS7:
<system.webServer>
<security>
<requestFiltering>
<!-- 1GB (the value is in Bytes) -->
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
我们现在可以进一步提升自定义验证属性,并启用客户端验证以避免浪费带宽。当然,只有HTML5 File API才能在上传之前验证文件大小。因此,只有支持此API的浏览器才能利用它。
所以第一步是让我们的自定义验证属性实现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;
}
}
以及剩下的就是配置自定义适配器:
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;
}, '');
答案 1 :(得分:1)
您可以在web.config中增加某些网址的请求最大长度:
<location path="fileupload">
<system.web>
<httpRuntime executionTimeout="600" maxRequestLength="10485760" />
</system.web>
</location>
答案 2 :(得分:-1)
我google了一下,并提出了以下两个网址,这些网址似乎表明此问题或异常最好在Global.asax中的应用程序错误事件中处理。