ASP.NET MVC: обработка загрузки превышает maxRequestLength

При загрузке файла на моем сайте MVC я стараюсь обрабатывать сбои при загрузке из-за того, что пользователь превышает границу maxRequestLength более изящно, чем, например, при отображении обычной пользовательской страницы ошибок. Я бы предпочел отобразить ту же страницу, на которую они пытаются опубликовать, но с сообщением, информирующим их о том, что их файл слишком велик... похоже на то, что они могут получить при ошибке проверки.

Я начинаю с идеи из этого вопроса:

Перехват "Превышена максимальная длина запроса"

НО, что я хочу сделать, вместо того, чтобы перейти на страницу с ошибкой (как они делают в этом вопросе), я хочу передать обработку исходному контроллеру, но с добавленной в ModelState ошибкой, указывающей на проблему. Вот некоторый код с комментариями, указывающими, где и что я хотел бы сделать. См. Вопрос выше для определения IsMaxRequestExceededEexception, что является чем-то вроде взлома, но я не нашел намного лучше.

Строка, которую я закомментировал, возвращает пользователя на нужную страницу, но, конечно, они теряют все изменения, которые могли внести, и я не хочу использовать Redirect здесь...

if (IsMaxRequestExceededException(Server.GetLastError()))
{
    Server.ClearError();
    //((HttpApplication) sender).Context.Response.Redirect(Request.Url.LocalPath + "?maxLengthExceeded=true");
    // TODO: Replace above line - instead tranfer processing to appropriate controlller with context intact, etc
    // but with an extra error added to ModelState.
}

Просто ищу идеи, а не полное решение; то, что я пытаюсь сделать, даже возможно?

1 ответ

Решение

Вот обходной путь: установите maxRequestLength свойство в вашем web.config до некоторого высокого значения. Затем напишите пользовательский атрибут проверки:

public class MaxFileSize : ValidationAttribute
{
    public int MaxSize { get; private set; }

    public MaxFileSize(int maxSize)
    {
        MaxSize = maxSize;
    }

    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file != null)
        {
            return file.ContentLength < MaxSize;
        }
        return true;
    } 
}

который можно использовать для украшения вашей модели вида:

public class MyViewModel
{
    [Required]
    [MaxFileSize(1024 * 1024, ErrorMessage = "The uploaded file size must not exceed 1MB")]
    public HttpPostedFileBase File { get; set; }
}

тогда вы можете иметь контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // TODO: Process the uploaded file: model.File

        return RedirectToAction("Success");
    }
}

и наконец вид:

@model MyViewModel

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <div>
       @Html.LabelFor(x => x.File)
       <input type="file" name="file" />
       @Html.ValidationMessageFor(x => x.File)
    </div>

    <p><input type="submit" value="Upload"></p>
}
Другие вопросы по тегам