Сегодня сделаем Drag and Drop форму для загрузки изображения на сайт.
Для ее реализации используем плагин Bootstrap File Input от Krajee.
Документация у плагина довольно обширная (правда вся она на английском), вы можете посмотреть ее по ссылке выше. Плагин предоставляет много возможностей. В рамках одной статьи рассмотреть их нереально. Но это и не является целью данной статьи.
Здесь я вам покажу, как мы можем реализовать форму с Drag and Drop полем, которое будет загружать изображение в определенную папку.
Сразу скажу, что в уроке я не буду подключать базу данных, чтобы не перегружать пост. Вместо сохранения в базе данных я буду просто сохранять картинку в папку, а когда мы повторно попадаем на страницу, буду отображать ее также подтягивая из папки.
На практике вы скорее всего будете сохранять имя картинки в базе данных, а после доставать его оттуда. Но в этом уроке для упрощения я этого делать не буду.
Итак начнем.
Подключаем всё необходимое для Drag and Drop зоны.
Во первых давайте разберемся со структурой нашего мини проекта. В папке проекта у меня будут всего 2 файла:
- form.php – файл, где будем моя форма
- index.php – файл-обработчик отправки формы.
Кроме этого мне понадобиться папка для хранения изображения. Назову ее images.
Откроем файл form.php и создадим базовую разметку. Здесь будет подключение всех необходимых внешних скриптов и стилей, которые обеспечат работу плагина, подключение скриптов и стилей самого плагина.
Также мы создадим форму.
Первый input должен иметь type=”file”. Также мы пропишем ему атрибут data-browse-on-zone-click=”true”, который обеспечит чувствительность drag&drop зоны к клику.
Сама форма должна иметь атрибут enctype=”multipart/form-data”. Это нужно для того, чтобы могли работать с глобальным массивом $__FILE в нашем обработчике. Метод у формы будет post, а в качестве action укажем наш файл обработчик index.php.
Также у нашей формы должен быть input типа submit. Это наша кнопка, которая будет отправлять форму.
На данном этапе у нас должен получится вот такой код.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Krajee</title> <!-- bootstrap 5.x or 4.x is supported. You can also use the bootstrap css 3.3.x versions --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" crossorigin="anonymous"> <!-- default icons used in the plugin are from Bootstrap 5.x icon library (which can be enabled by loading CSS below) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.min.css" crossorigin="anonymous"> <!-- the fileinput plugin styling CSS file --> <link href="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.5/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" /> <!-- the jQuery Library --> <script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script> <!-- sortable.min.js is only needed if you wish to sort / rearrange files in initial preview. This must be loaded before fileinput.min.js --> <script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.5/js/plugins/sortable.min.js" type="text/javascript"></script> <!-- bootstrap.bundle.min.js below is needed if you wish to zoom and preview file content in a detail modal dialog. bootstrap 5.x or 4.x is supported. You can also use the bootstrap js 3.3.x versions. --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script> <!-- the main fileinput plugin script JS file --> <script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.5/js/fileinput.min.js"></script> </head> <body> <div class="container"> <form action="index.php" method="post" enctype="multipart/form-data"> <input id="main_slider" required name="main_slider" type="file" accept="image/*" data-browse-on-zone-click="true"> <input type="submit" value="SEND"> </form> </div> </body> </html>
Вызываем скрипт Drag&Drop
Пока что ничего интересного мы в браузере не увидим.
Чтобы увидеть Drag and drop зону мы должны написать немного js скрипта.
Пропишем его до закрывающего тега body нашей страницы.
<script> $("#main_slider").fileinput({ showUpload: false, showRemove: true, initialPreviewShowDelete: false, allowedFileExtensions: ["jpg", "png", "gif"], }); </script>
Как вы могли заметить, у нашего input есть id. Благодаря этому мы подключаем к нему fileinput. В подключении мы указываем, что:
- не хотим отображать кнопку upload,
- хотим отображать кнопку remove,
- не хотим отображать кнопку удаления у превьюшки (но это мы увидим чуть позже),
- и указываем допустимые типы файлов для загрузки.
Теперь мы увидим следующее, если откроем нашу страницу в браузере.
Пробуем выбрать изображение и вот такой результат получаем.
Сохраняем картинку в папке
Всё отлично, но если мы нажмем на кнопу Send, то ничего не произойдет, потому что мы еще не написали обработчик для отправки нашей формы.
Вы помните, что в качестве action для формы мы указали index.php. Пришло время написать в нем код.
Итак, что мы хотим?
Мы хотим получить картинку, закодировать ей новое имя и сохранить ее в папке images.
В данном примере у меня в этой папке всегда будет только одна картинка, поэтому когда я снова буду выбирать другую картинку, то при сохранении я буду очищать папку и записывать туда новую картинку.
В этом примере я это делаю для того, чтобы не усложнять урок добавлением имени картинки в базу данных, а всегда извлекать картинку для отображения из папки. Для этого мне нужно, чтобы в папке всегда была только 1 картинка. На практике, вам вероятно это будет не нужно.
Код файла index.php с комментариями:
<?php if(isset($_FILES['main_slider']) && $_FILES['main_slider']['name'] != ""){ //очищаю директорию array_map('unlink', glob("images/*")); // кодирую имя картинке $image_code = md5(rand(10000, 10000000)); // разделяю path на части, чтобы извлечь разрешение файла $path_parts = pathinfo($_FILES['main_slider']['name']); // перемещаю файл в папку move_uploaded_file($_FILES['main_slider']['tmp_name'], 'images/' . $image_code . '.'.$path_parts['extension']); // редирект обратно на страницу header('Location: form.php'); }
В принципе здесь комментарий к каждой строке, поэтому больше особо добавить нечего.
Теперь при сохранении файл будет сохраняться в папке images, но попав обратно на страницу мы его не увидим. А нам хотелось бы видеть превью загруженного файла.
Для этого вернемся в файл form.php и немного его модифицируем.
Во-первых я извлеку имя файла, который лежит в папке. Для этого добавлю вот такой php-код. (Напоминаю, что вы вероятно будете извлекать имя файла из базы данных).
<?php if ($handle = opendir(__DIR__.'/images')) { $files = scandir(__DIR__.'/images'); $file = ''; foreach($files as $v){ if($v != '.' && $v != '..'){ $file = $v; } } closedir($handle); } ?>
Теперь в переменной $file у меня лежит имя загруженного файла.
Мне нужно передать его в javascript код и добавить некоторые параметры в вызов fileinput.
Вот так будет выглядеть модифицированный крипт, который мы ранее прописали до закрывающего тега body.
<script> let url = "images/<?php echo $file;?>"; //передаем переменную $file в javascript $("#main_slider").fileinput({ showUpload: false, showRemove: true, initialPreviewShowDelete: false, allowedFileExtensions: ["jpg", "png", "gif"], initialPreviewAsData: true, initialPreview: [url], //наш файл initialPreviewConfig: [ {downloadUrl: url}, ], }); </script>
Мы формируем переменную url – это путь к нашей картинке. Здесь же мы передаем переменную $file из php.
Далее мы устанавливаем параметры для initialPreview.
- initialPreviewAsData: true – чтобы отобразить превью
- initialPreview – массив с путями к файлам (в данном случае у нас только 1 файл)
- nitialPreviewConfig – массив объектов. В данном случает у нас только 1 файл и поэтому только 1 объект. Мы указали в нем только downloadUrl, но там может быть и другая информация, такая как title и прочее. Подробнее можете посмотреть в примерах документации.
После всего этого мы можем загружать картинки и при редиректе, попадая обратно на страницу мы будем видеть их превью в форме.
Если загрузим новый файл, то старый затрется и мы увидим превью нового файла. Соответственно в папку попадет новый файл.
Надеюсь этот урок был вам полезен.