Skip to main content
AJAX и PHP

Ajax и PHP. Загрузка изображения на сервер

В наше время веб-сайты становятся все более интерактивными. Это касается не только специализированных сервисов, но и обычных интернет магазинов, блогов и небольших сайтов. Основной особенностью является асинхронный JavaScript и XML сокращенно AJAX. Эта технология позволяет браузеру в фоновом режиме общаться с веб-сервером и при обновлении данных, веб-страница не перезагружается полностью. Другими словами, мы можем делать запросы и получать ответы от сервера не перезагружая страницу в браузере.


Поскольку наиболее популярным языком для разработки веб-приложений является PHP, то сегодня мы будем использовать связку AJAX и PHP. Пример будет хорош для понимания основных принципов работы с AJAX и PHP.

На самом деле особых сложностей быть не должно, алгоритм действий:

  • Выбрать картинку
  • Нажать кнопку “Отправить”
  • Перехватить вызов формы с помощью JavaScript (jQuery)
  • Передать содержимое в специальный php скрипт-обработчик
  • Вернуть результат выполнения
  • Обработать результат при помощи JavaScript (jQuery)
  • Вывести пользователю информацию о загрузке

Кратко о jQuery и AJAX

Немного отклонюсь от темы и объясню что такое jQuery. jQuery — это специальная JavaScript библиотека, которая помогает упростить разработку веб приложений в несколько раз, также данная библиотека предоставляет API для работы с AJAX. Простыми словами, мы напишем меньше кода, чем если бы это делали на чистом JS.

Ajax позволяет не перезагружая веб-страницу, обмениваться данными с веб-сервером и обновлять ее содержимое.

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

Мы разберем одну из проблем, которую мне однажды пришлось решать, а именно — загрузка изображения на сайт с предварительным просмотром. Если вы меняли аватарку в вконтакте, вы понимаете о чем я пишу.

Нам понадобится 3 простых файла, это:

  • Страница с формой
  • php обработчик
  • файл js

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ajax Upload</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="main.css">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script type="text/javascript" src="ajaxupload.js"></script>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-md-6 col-md-offset-3">
          <h1>Image upload</h1>
          <div class="image-preview">
            <img id="preview" src="" alt="">
          </div>
          <form id="upload-image" enctype="multipart/form-data">
            <div class="form-group">
              <label for="image">Image file:</label>
              <input type="file" name="image" id="image">
            </div>
            <input type="submit" class="btn btn-default">
          </form>
          <div id="result">
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

Обычная html страница с формой. Обратите внимание на enctype="multipart/form-data", это нужно для передачи файлов, параметр указывает на способ кодирования данных. Если передаете файлы, значение всегда должно быть multipart/form-data.

handler.php

// Проверяем установлен ли массив файлов и массив с переданными данными
if(isset($_FILES) && isset($_FILES['image'])) {

  //Переданный массив сохраняем в переменной
  $image = $_FILES['image'];

  // Проверяем размер файла и если он превышает заданный размер
  // завершаем выполнение скрипта и выводим ошибку
  if ($image['size'] > 200000) {
    die('error');
  }

  // Достаем формат изображения
  $imageFormat = explode('.', $image['name']);
  $imageFormat = $imageFormat[1];

  // Генерируем новое имя для изображения. Можно сохранить и со старым
  // но это не рекомендуется делать
  $imageFullName = './images/' . hash('crc32',time()) . '.' . $imageFormat;

  // Сохраняем тип изображения в переменную
  $imageType = $image['type'];

  // Сверяем доступные форматы изображений, если изображение соответствует,
  // копируем изображение в папку images
  if ($imageType == 'image/jpeg' || $imageType == 'image/png') {
    if (move_uploaded_file($image['tmp_name'],$imageFullName)) {
      echo 'success';
    } else {
      echo 'error';
    }
  }
}

Это очень упрощенный обработчик. Имя картинки я сгенерировал использовав функцию hash. Хорошей практикой считается изменять имена файлов при загрузке их на сервер.

ajaxupload.js

$(document).ready(function () {

  function readImage ( input ) {
    if (input.files && input.files[0]) {
      var reader = new FileReader();

      reader.onload = function (e) {
        $('#preview').attr('src', e.target.result);
      }

      reader.readAsDataURL(input.files[0]);
    }
  }

  function printMessage(destination, msg) {

    $(destination).removeClass();

    if (msg == 'success') {
      $(destination).addClass('alert alert-success').text('Файл успешно загружен.');
    }

    if (msg == 'error') {
      $(destination).addClass('alert alert-danger').text('Произошла ошибка при загрузке файла.');
    }

  }

  $('#image').change(function(){
    readImage(this);
  });

  $('#upload-image').on('submit',(function(e) {
    e.preventDefault();

    var formData = new FormData(this);

    $.ajax({
      type:'POST', // Тип запроса
      url: 'handler.php', // Скрипт обработчика
      data: formData, // Данные которые мы передаем
      cache:false, // В запросах POST отключено по умолчанию, но перестрахуемся
      contentType: false, // Тип кодирования данных мы задали в форме, это отключим
      processData: false, // Отключаем, так как передаем файл
      success:function(data){
        printMessage('#result', data);
      },
      error:function(data){
        console.log(data);
      }
    });
  }));
});

В этом скрипте происходит самое интересное. При помощи функции readImage() мы будем считывать файл с поля формы и передавать его в блок для предварительного просмотра. Создается объект FileReader. Он позволяет веб-приложению считывать содержимое файла на компьютере пользователя. Событие .onload сработает когда содержимое будет считано, при помощи этого события мы выведем изображение в блок предварительного просмотра.
И напоследок, метод .readAsDataURL() запускает процесс чтения файла, по завершению чтения будет выполнено событие .onload и картинка появится у вас на экране.

Функция printMessage создана для вывода информации об успешной или провалившейся попытке загрузки файла. Подробно не рассматриваем, ничего особенного не представляет.

Перехват формы и её обработка. При клике на кнопку «Отправить» событие будет перехвачено скриптом и при помощи функции .preventDefault() форма не отправит данные в index.html. .preventDefault() служит для отмены вызова каких-либо событий.

Объект FormData нужен нам для создания POST запроса к нашему скрипту, это намного проще чем вписывать каждый элемент формы в строку. Создали объект, заполнили данными, отдали в наш ajax.

Ну и собственно сам запрос AJAX. Поскольку мы используем библиотеку jQuery, составить и выполнить такой запрос не вызовет у вас никаких проблем.

Собственно, на этом и закончим. Изображение загружается, страница не перезагружается, все довольны. Если у вас возникают вопросы или предложения, пишите комментарии.

Хорошего дня и успехов 🙂

8 Комментарии “Ajax и PHP. Загрузка изображения на сервер

  1. Здравствуйте! А ссылку можно где это реализовано? Посмотреть бы. Спасибо за ранее.

  2. Большая ошибка делать так:
    $imageFormat = explode(‘.’, $image[‘name’]);
    $imageFormat = $imageFormat[1];
    В этом случае на сервер можно загрузить любой файл под видом картинки. Скрипт возьмёт только первый элемент массива «imageFormat». Здесь можно будет манипулировать такими значениями как fileName.js.jpg или FileName.php.jpg. При этом, на сервер будет загружен файл с расширением «JS» или чего хуже «PHP». При загрузки PHP файла, с сервером можно будет делать, всё что угодно.
    Следует делать так:
    $imageFormat = explode(‘.’, $image[‘name’]);
    $imageFormat = array_pop($imageFormat);

  3. Спасибо большое. Это то, что я искала. Ваш код работает безупречно. Но еще есть одна большая проблема. Не загружаются на сайт фотки из галереи смартфона в Яндексе или стандартном браузере. В Google такой проблемы нет. Причем нет и ответа на все проверки по типу и наличия временного файла, ни по размеру. Нигде не могу найти решение этой проблемы. Помогите.

  4. Добрый день, Александр. Могу я Вас попросить пояснить как измениться JS-скрипт, если в форме 3 input типа file. И я хочу передать три изображение одной формы.
    Я читал, что для этого нужен цикл и последовательно передавать каждый файл, но вот как это реализовать не пойму. Буду благодарен за ответ. Спасибо!

    1. Если 3 input, то им нужно просто дать разные имена или массив. Если имена разные, то обрабатываем каждое поле, если массив — просто обрабатываем через foreach

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *