Как обрабатывать ошибки проверки (проверки) на стороне сервера при загрузке файла - PullRequest
0 голосов
/ 15 октября 2019

У меня есть форма, которая проверена на стороне сервера, и если форма имеет недопустимые элементы, модель возвращается в представление, а JavaScript затем выделяет поля, которые являются недействительными. Это многокомпонентная форма, которая содержит тип входного файла для загрузки файла. Я использую Visual Studio 2017, ASP.Net Core 2.1 и шаблон проектирования ASP.Net MVC.

Проблема : пользователь отправляет форму и имеет прикрепленный файл, но форма недопустима из-заодно или несколько полей ввода. При передаче модели обратно в представление с ошибками проверки файл больше не прикрепляется, поскольку вы не можете заполнить файл типа ввода с сервера (по крайней мере, я не знаю, думаю, что это функция безопасности).

Требуемое поведение : пользователю не нужно повторно выбирать файл на входе для повторной загрузки.

Текущее решение : Я сериализую и сохраняю загруженный файл в Session на сервере, а затем устанавливаю свойство Model, которое сообщает представлению, что файл сохраняется в сеансе, и удаляет файл типа ввода для загрузки, а затем при повторной отправке, если форма действительна, десериализовать файл из сеанса, сделать то, что мне нужно сделать с файлом, и удалить его из сеанса.

Вопрос : Есть ли лучший способ справиться с этим? Если да, предложите пример документации или совета.

Ответы [ 2 ]

1 голос
/ 15 октября 2019

Как вы уже догадались, из соображений безопасности ни один из основных браузеров не предоставляет вам доступ к фактическому пути к файлу, выбранному пользователем. Код вашего сервера не получит реальный путь, и даже JavaScript не имеет доступа к нему. Вместо этого браузер генерирует поддельный путь, и единственное реальное значение в нем - это имя файла.

По этой причине единственный способ сохранить файл в вашем текущем дизайне (то есть стандартной форме) после формыПредставляется так, как вы это сделали, как вы описали в своем вопросе. Очевидно, что это не очень хороший способ, особенно если файл слишком большой, поэтому каждое обратное путешествие на сервер займет много времени.

Чтобы решить его по-другому, вам нужно будет изменить дизайн. Вам нужно, чтобы браузер сохранил значение реального пути. Единственный способ сделать это, не отправляя форму. Таким образом, вам нужно отправить значения формы без отправки формы. Единственный способ сделать это, о котором я могу подумать, это отправить форму с помощью Ajax. Это означает, что результат проверки на стороне сервера должен будет возвращаться как ответ Ajax (обычно JSON, но может быть сериализован другими способами, если хотите), а затем JavaScript примет этот ответ и отобразит ошибки в форме кактребуется. Таким образом, файл по-прежнему повторно отправляется на сервер каждый раз, но, по крайней мере, серверу не нужно отправлять его обратно клиенту, как описано в вопросе. Это экономит половину полосы пропускания, но требует больше программирования. Это все еще не рекомендуется, если файл может быть большим. В этом случае, вероятно, лучше позволить пользователю повторно выбрать файл, а не ждать долгое время для повторной загрузки файла.

Чтобы добавить помощника Ajax в .Net Core, вы можетеПросто скачайте файл JavaScript из проекта GitHub и укажите ссылку на него в заголовке вашего HTML. Однако я предпочитаю ссылаться на него только на тех страницах, где мне это нужно, потому что большинству страниц это не нужно. Что я делаю, сначала создаю для него частичное представление:

<environment names="Development">
    <script src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.js"></script>
</environment>
<environment exclude="Development">
    <script src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.min.js"></script>
</environment>

Вы можете использовать CDN, если хотите. Я не могу найти CDN, кроме cdn.jsdelivr.net, и не могу найти хороший резервный тест, поэтому я оставил asp-fallback-test пустым:

<environment names="Development">
    <script src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.js"></script>
</environment>
<environment exclude="Development">
    <script src="https://cdn.jsdelivr.net/npm/jquery-ajax-unobtrusive@3.2.6/dist/jquery.unobtrusive-ajax.min.js"
        asp-fallback-src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.min.js"
        asp-fallback-test=""
        crossorigin="anonymous"
        integrity="sha256-PAC000yuHt78nszJ2RO0OiDMu/uLzPLRlYTk8J3AO10="></script>
</environment>

В любом случае, назовите этот файл как угодно, скажем так_AjaxScriptsPartial.cshtml. Теперь в представлении, где вам это нужно, добавьте его следующим образом:

@section Scripts {
    @{ await Html.RenderPartialAsync("_AjaxScriptsPartial"); }
}

Вот хорошее объяснение того, как его использовать: Использование ненавязчивого Ajax в страницах Razor .

Кроме того, вы можете сохранить свой текущий дизайн, но вместо сериализации файла и отправки его обратно в браузер, сохраните его на сервере и отправьте URL-адрес в браузер. Теперь в JavaScript замените поле ввода файла простым сообщением, например «Файл успешно загружен» или любым другим способом, чтобы указать пользователю, что файл не нужно выбирать повторно. После повторной отправки формы и успешной проверки всех серверов получите физический файл на сервере. Ваш код должен знать, загружать ли файл или получать его с сервера (проверяя, есть ли в поле ввода файла файл). Это также должно знать, где взять это на сервере. Этот способ будет хорошо работать для файлов любого размера, потому что файлы загружаются только один раз, но требуют некоторой работы.

1 голос
/ 15 октября 2019

Я не уверен в том, что вы делаете проверку, но можно ли ее перенести в интерфейс? Обычно проверка в интерфейсе больше для удобства пользователя. (Например, неправильные форматы, поля оставлены пустыми, неправильный тип данных в поле). Если это так, я бы переместил его в интерфейс, если нет, вы можете оставить его в фоновом режиме.

Вы можете проверять поля в форме, используя AJAX, когда они покидают фокус. Это может гарантировать, что при отправке формы поля в форме всегда будут правильными. Я считаю, что правильное сочетание проверки на стороне сервера и на стороне сервера работает лучше всего, и в нем не все есть.

Грубый пример ниже отправляет ajax-запрос к контроллеру для проверки поля ввода при запуске метода onblur. Он будет устанавливать границу зеленого или красного цвета, если он прошел проверку, и отображать сообщение, если оно есть. Просто убедитесь, что ваша модель соответствует тому, что вы отправляете в своем запросе:

JS:

<script>
    function validate() {
        var input = { input: $('#one').val() };

        $.ajax({
            url: 'ValidateTextBox/',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify(input),
            success: function (data) {
                if (JSON.parse(data.Result)) {
                    $('#one').css('border', '5px solid green');
                } else {
                    $('#one').css('border', '5px solid red');
                }
                $('#result').text(data.Message);
            }
        })
    }
</script>
<input id="one" type="text" onblur="validate()"/>
<label id="result"></label>

Controller.cs

[HttpPost]
public ActionResult ValidateTextBox(Dummy data)
{
    int result = 0;

    if (!int.TryParse(data.input, out result)) {
        return Json(new { Result = false, Message = "Please enter in numbers" });
    }
    return Json(new { Result = true, Message = "Success" });
}

Model.cs

public class Dummy
{
    public string input { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...