Convalida per file di grandi dimensioni al momento del caricamento

Sto lavorando con c # MVC 2 e ASP.NET. Una delle mie forms include un campo di input del file che consente di selezionare qualsiasi tipo di file che verrà poi convertito in un blob e salvato nel database. Il mio problema è che ogni volta che un utente seleziona un file che supera una certa quantità di Mb (circa 8) ottengo un errore di pagina che dice quanto segue:

The connection was reset The connection to the server was reset while the page was loading. 

Non mi dispiace che ci sia un limite di 8 Mb per i file che gli utenti stanno caricando, tuttavia ho bisogno di fermare l’errore corrente e visualizzare un messaggio di convalida appropriato (preferibilmente con la funzione ModelState.AddModelError). Qualcuno può aiutarmi? Non riesco a ‘cogliere’ l’errore prima che accada qualcos’altro nella pagina da quando sta accadendo prima che arrivi nella funzione di upload all’interno del controller.

Una possibilità è scrivere un attributo di convalida personalizzato:

 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()); } } 

e quindi potresti avere un modello di visualizzazione:

 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"); } } 

e una vista:

 @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)  } 

Ora, ovviamente, per far funzionare tutto questo, dovrai aumentare la dimensione massima consentita per il caricamento del file in web.config ad un valore sufficientemente grande:

   

e per IIS7:

         

Ora possiamo portare il nostro attributo di convalida personalizzato un ulteriore passo avanti e abilitare la validazione lato client per evitare di sprecare larghezza di banda. Naturalmente verificando la dimensione del file prima del caricamento è ansible solo con l' API file HTML5 . Di conseguenza, solo i browser che supportano questa API potranno trarne vantaggio.

Quindi il primo passo è fare in modo che il nostro attributo di convalida personalizzato implementa l'interfaccia IClientValidatable che ci permetterà di albind un adattatore personalizzato in 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 GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ErrorMessage = FormatErrorMessage(_maxFileSize.ToString()), ValidationType = "filesize" }; rule.ValidationParameters["maxsize"] = _maxFileSize; yield return rule; } } 

e tutto ciò che rimane è configurare l'adattatore personalizzato:

 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; }, ''); 

Puoi aumentare la lunghezza massima della richiesta per alcuni URL in web.config:

      

Ho cercato un po ‘su google e ho trovato i seguenti due URL che sembrano suggerire che questo problema o eccezione vengano gestiti al meglio nell’evento Error dell’applicazione in Global.asax.

  1. Catching ‘Lunghezza massima richiesta superata’
  2. Come gestire l’eccezione “Lunghezza massima richiesta superata”