Загрузка файлов на сервер через Ajax

122
24 января 2021, 05:00

Всем привет.

Помогите разобраться с моей проблемой. Нужно через Ajax оправить файл на сервер, но ещё и другие поля. Мне в любом случае сервер возвращает 422 ошибку, как и положено, даже если все поля заполнены и файл загружен.

На странице есть поле для загрузки файла и поля с данными. Код ниже:

<input type="text" class="form-control" id="userName" name="userName" autofocus>
<input type="email" class="form-control required" id="email" name="email" required>
<input type="text" name="homePage" class="form-control" id="homePage">
<textarea class="form-control" id="message" name="message" rows="5" required></textarea>
<div class="row justify-content-center mb-3">
        <div class="col-6 load">
            <label for="basic-url">Your image or file</label><span class="required"></span>
            <img id="info" src="/img/question.png" alt="question">
            <input id="input-id" type="file" class="file" data-preview-file-type="text">
        </div>
</div>

Это кнопка, по которой должны данные отправиться на сервер. Код ниже:

<div class="row justify-content-center mb-5">
        <div class="col-6 text-right">
            <button type="button" class="btn-submit">Add comment</button>
        </div>
</div>

По кнопке отрабатывает следующий код JS. Код ниже:

$('.btn-submit').click(function () {
        let file_data = $('#input-id').prop('files')[0];
        let form_data = new FormData();
        form_data.append('file', file_data);
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });
        $.ajax({
            type: 'POST',
            url: '/comment',
            data: {
                file: form_data,
                userName: $('#userName').val(),
                email: $('#email').val(),
                homePage: $('#homePage').val(),
                message: $('#message').val()
            },
            processData: false,
            contentType: false,
            cache: false,
            success: function (successResponse) {
                alert(successResponse);
            },
            error: function (errorResponse) {
                console.log(errorResponse);
            }
        });
    })

В строках 2-4, идёт загрузка данных с поля формы в переменную. Этот кусок кода нашёл в интернете. Вместе с ним было написано, что при отправке файлов через Ajax нужно добавить вот такие атрибуты. Код ниже:

processData: false,
contentType: false,
cache: false,

Этот запрос принимает метод store() в моём контроллере. Код ниже:

 public function store(CommentRequest $request)
    {
        if ($request->ajax()) {
            return view('welcome');
        }
        return view('errors.404');
    }

В первую очередь в классе CommentRequest проверяются пришедшие данные по заданным правилам. Код ниже:

public function rules()
    {
        return [
            'userName' => 'required',
            'email' => 'required',
            'message' => 'required',
            'file' => 'required|image|mimes|:png,jpg:max:2048',
        ];
    }

Даже если все поля заполняю, файл в поле загружаю, нажимаю кнопку отправить и мне возвращает массив ошибок. userName, email, message, file - the <моё поле> field is required.

Если кому-то нужно, оставляю ссылку на проект https://github.com/Road-To-The-Dream/Comments/tree/feature/createComment

Answer 1

У вас некоторые ошибки при формировании ajax запроса.

<!--
     В качестве примера разметка формы была упрощена.
     В форму обязательно помещаем `csrf` токен.
-->
<form id="comment_form" action="/comment" enctype="multipart/form-data" method="post">
  @csrf
  <input type="text" name="userName" value="{{ old('userName') }}" autofocus />
  <input type="email" name="email" value="{{ old('email') }}" required />
  <input type="file" name="attach" />
  <button type="submit">Add comment</button>
</form>
<script type="text/javascript">
  $(document).ready(function() {
    $("#comment_form:first").submit(function(event) {
      // Отменяем стандартное поведение формы.
      event.preventDefault();
      // Собираем данные с формы.
      // Здесь будут все поля у которых есть `name`,
      // включая загружаемый файл с `name="attach"` и `_token`
      var data = new FormData(this);
      // Отправляем запрос.
      $.ajax({
        type: 'POST',
        url: this.action, // атрибут `action="..."` из формы.
        cache: false, // запрошенные страницы не будут закешированы браузером.
        data: data, // data: data - больше ничего тут не надо!
        dataType: 'json', // чтобы jQuery распарсил `success` ответ.
        processData: false, // чтобы jQuery не обрабатывал отправляемые данные.
        contentType: false, // чтобы jQuery не передавал в заголовке поле `Content-Type` совсем.
        success: function(data) {
          alert(data.message);
        },
        error: function(error) {
          alert('Ошибка отправки сообщения');
          var json = error.responseJSON;
          // Обработка ошибок валидации.
          if(422 === error.status) {
            var errors = json.errors;
            for (var error in errors) {
              console.log(error, errors[error][0])
            }
          } else {
            console.log(json.message)
          }
        }
      });
    });
  });
</script>

Дальше выполняете необходимую валидацию на стороне сервера CommentRequest.

jpg - это расширение файла, а jpeg - это mime.

Правило для валидатора mimes:jpeg проверяет MIME тип файла, читая содержимое файла и угадывая его MIME тип, а не просто по расширение. Подробнее ...

Попробуйте оставить только одно правило mimes:jpeg, взять файл с расширением png, переименовать его расширение на jpeg: валидатор не пропустит, хотя расширение jpeg.

READ ALSO
Выполнение кода в определенный момент Java

Выполнение кода в определенный момент Java

Подскажите, как выполнить какой-то код, допустим, ровно в 18:00?

109
Дубликаты в HashSet

Дубликаты в HashSet

Хотел спросить, вывожу в консоль данный код и выводит:

147
Сравнение двух изображений

Сравнение двух изображений

Пишу программу, используя эту статью: https://moluchru/archive/115/31188/ Мой алгоритм не правильно распознает

104