Please consider the validation attribute to validate the file size at the client side using HTML5 File API and JavaScript. Below is sample which includes a custom validator of ASP.NET Core 3.1 MVC used for validating the size and type of uploading file:
Model and Custom Validator
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Globalization;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace MvcCoreApp.Models
{
// Model
// See attribute [FileValidation(50000, "image/jpeg")] below.
// file size is limited to 50000 and file type to "image/jpeg"
public class FileUpload
{
[Required(ErrorMessage = "{0} is required.")]
public string Name { get; set; }
[Display(Name = "Upload file")]
[Required(ErrorMessage = "{0} is required.")]
[FileValidation(50000, "image/jpeg")]
public IFormFile PostedFile { get; set; }
}
// Custom validator attribute
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class FileValidationAttribute : ValidationAttribute,
IClientModelValidator
{
private readonly long size;
private readonly string type;
public FileValidationAttribute(long size, string type)
{
this.size = size;
this.type = type;
this.ErrorMessage = "{0} must be less than {1} byte, {2}";
}
public override string FormatErrorMessage(string displayName)
{
return String.Format(CultureInfo.CurrentCulture,
ErrorMessageString, displayName,
this.size, this.type);
}
public override bool IsValid(object value)
{
var postedFile = value as IFormFile;
if (postedFile == null || postedFile.Length == 0)
{
return false;
}
if (postedFile.Length <= this.size &&
postedFile.ContentType == this.type)
{
return true;
}
return false;
}
// method for IClientModelValidator
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(
context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes,
"data-val-filevalidation", errorMessage);
MergeAttribute(context.Attributes,
"data-val-filevalidation-size", this.size.ToString());
MergeAttribute(context.Attributes,
"data-val-filevalidation-type", this.type);
}
// helper used in above AddValidation method
private bool MergeAttribute(IDictionary<string, string> attributes,
string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}
}
View
@model MvcCoreApp.Models.FileUpload
@{
ViewData["Title"] = "Upload";
}
<h1>Upload</h1>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Upload" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger">
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PostedFile" class="control-label"></label>
<input type="file" asp-for="PostedFile" />
<br />
<span asp-validation-for="PostedFile" class="text-danger">
</span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script type="text/javascript">
//<![CDATA[
$.validator.addMethod("filevalidation",
function (value, element, parameters){
// confirm if HTML5 File API is supported
if (window.File && window.FileList) {
if (element.files[0] == undefined ||
element.files[0] == null) {
return true;
}
if (element.files[0].type != parameters.type) {
return false;
}
if (element.files[0].size > Number(parameters.size)) {
return false;
}
return ture;
} else {
return ture;
}
});
$.validator.unobtrusive.adapters.
add("filevalidation", ["type", "size"], function (options) {
var value = {
size: options.params.size,
type: options.params.type
};
setValidationValues(options, "filevalidation", value);
});
// helper method copied from jquery.validate.unobtrusive.js
function setValidationValues(options, ruleName, value) {
options.rules[ruleName] = value;
if (options.message) {
options.messages[ruleName] = options.message;
}
}
//]]>
</script>
}
Comtroller / Action Method
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using MvcCoreApp.Models;
using Microsoft.AspNetCore.Http;
using System.IO;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace MvcCoreApp.Controllers
{
public class ValidationController : Controller
{
public IActionResult Upload()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Upload(FileUpload model)
{
string result = "";
IFormFile postedFile = model.PostedFile;
if (ModelState.IsValid)
{
string filename = Path.GetFileName(postedFile.FileName);
result = filename + " (" + postedFile.ContentType + ") - " +
postedFile.Length + " bytes uploaded";
}
else
{
result = "upload fail";
}
ViewBag.Result = result;
return View();
}
}
}