Ajax Upload

Асинхронная загрузка файлов на сервер PHP + AJAX

Про загрузку файлов на сервер я писал здесь. Сегодня я расскажу про асинхронную загрузку файлов на сервер.

В настоящее время довольно популярным решением для веб-сайтов является работа пользователя со страницей без ее перезагрузки. В большинстве своём это делается с помощью Ajax – технологии асинхронного взаимодействия с сервером, основанной на объекте XMLHttpRequest .

В этой статье рассмотрим простое решение одной из самых распространенных задач – асинхронная загрузка файла на сервер при помощи PHP. Задача будет следующая: На странице (предположим, что это страница в личном кабинете пользователя) есть форма с input типа file и кнопка Отправить . Ниже находится контейнер с картинкой (аватар пользователя по задумке) в который асинхронно подгружается картинка после выполнения AJAX запроса. И по умолчанию она просто выводится из базы данных. То есть, при загрузке картинки новое сгенерированное название будет записываться в БД, сама картинка под этим названием загружаться на сервер и выводится в контейнере взамен предыдущей. И всё это асинхронно.

Сразу скажу, что я по бОльшей степени преследовал цель описать сам процесс загрузки, особо не сосредотачиваясь на «элегантности» кода ). Кто как захочет использовать этот код. Кто-то кусочек нужный возьмёт, кто-то целый класс напишет на его основе, кто-то переделает для себя, кто-то вовсе не будет его использовать никак. Тем более, там действительно, нужна доработка под боевые задачи. Например, валидацию на MIME-типы (и другие проверки) нужно делать ещё в JS до попадания данных скрипту PHP. В скрипт данные должны приходить отвалидированные. Или при загрузке картинки удалять на сервере старую картинку. Поэтому я решил, что полезнее будет подробно описать процесс, нежели допиливать до идеала то, что каждый для себя доработает как нужно. Поехали.

Безусловно, подключаем jQuery (если ещё в проекте нигде данная библиотека не подключена):

Простая разметка HTML формы и картинка из базы. Предположим, что у вас уже есть база данных и в базе уже есть таблица (например, user ). В блоке с id=»photo-content» выводится картинка из базы. Я весь этот код помещу в файле index.php .

prepare($query); $stmt->execute([$id]); $image = $stmt->fetchColumn(); ?>     
Image upload

Image
#wrapper < width: 60%; margin: 20px auto; >form button < margin-bottom: 50px; >input[type=text], input[type=file] < margin-bottom: 20px; >#process
$(document).ready(function()< $("#form-file-ajax").on('submit', function(e)< e.preventDefault(); var formData = new FormData(); var form = $(this); formData.append('file', $('#file').prop("files")[0]); $.ajax(< url: form.attr('action'), type: form.attr('method'), processData: false, contentType: false, cache:false, dataType : 'text', data: formData, // Будет вызвана перед осуществлением AJAX запроса beforeSend: function()< $('#process').fadeIn(); >, // будет вызвана после завершения ajax-запроса // (вызывается позднее функций-обработчиков успешного (success) или аварийного (error) complete: function () < $('#process').fadeOut(); >, success: function(data)< //form[0].reset(); data = JSON.parse(data); var image = '
'; var photoContent = $("#photo-content"); photoContent.html(''); photoContent.append(image); >, error: function(data) < console.log(data); >>); >); >);
 // Записать имя файла в БД $db = new PDO('mysql:host=localhost;dbname=ajax', 'root', 'password'); $user_id = 1; $query = "UPDATE `user` SET `avatar` = :avatar WHERE `id` = :user_id"; $params = [':avatar' => $file, ':user_id' => $user_id]; $stmt = $db->prepare($query); if (!$stmt->execute($params)) < throw new Exception('Произошла ошибка при записи в БД!'); >// Записать в $data имя файла $data = ['file' => $file]; echo json_encode($data); > catch (Exception $e) < die($e->getMessage()); > > > // Генерируем уникальное имя для файла function randomFileName($extension = false) < $extension = $extension ? '.' . $extension : ''; do < $name = md5(microtime() . rand(0, 9999)); $file = $name . $extension; >while (file_exists($file)); return $file; >

Вот и все. Ясное дело, что это не идеальное решение и как использовать его (если использовать) решать каждому самостоятельно. Может быть в дальнейшем я напишу специальный класс со всеми недочётами. А пока, как-то так.

Для работы данного примера без ошибок не забудьте заменить все адреса своими и указать корректные доступы к базе данных!

Источник

Загрузка файлов через jQuery AJAX

В преведущей статье был приведен пример отправки файлов через AJAX с помощью плагина «jQuery Form Plugin». Но файлы можно отправить и обычным методом jQuery $.ajax() .

Читайте также:  Вывести строку си шарп

Отправка одного файла

Для примера возьмем поле и элемент div с id=»result» для вывода результата.

Чтобы отправить файл нужно отправить его бинарный данные, для этого есть объект FormData, поддерживается он всеми современными браузерами.

   

Помимо использования formData, в настройках $.ajax нужно указать параметры contentType: false и processData: false т.к. без них файл не отправится.

Код скрипта upload.php

 $input_name = 'file'; // Разрешенные расширения файлов. $allow = array(); // Запрещенные расширения файлов. $deny = array( 'phtml', 'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'phps', 'cgi', 'pl', 'asp', 'aspx', 'shtml', 'shtm', 'htaccess', 'htpasswd', 'ini', 'log', 'sh', 'js', 'html', 'htm', 'css', 'sql', 'spl', 'scgi', 'fcgi', 'exe' ); // Директория куда будут загружаться файлы. $path = __DIR__ . '/uploads/'; $error = $success = ''; if (!isset($_FILES[$input_name])) < $error = 'Файл не загружен.'; >else < $file = $_FILES[$input_name]; // Проверим на ошибки загрузки. if (!empty($file['error']) || empty($file['tmp_name'])) < $error = 'Не удалось загрузить файл.'; >elseif ($file['tmp_name'] == 'none' || !is_uploaded_file($file['tmp_name'])) < $error = 'Не удалось загрузить файл.'; >else < // Оставляем в имени файла только буквы, цифры и некоторые символы. $pattern = "[^a-zа-яё0-9,~!@#%^-_\$\?\(\)\\[\]\.]"; $name = mb_eregi_replace($pattern, '-', $file['name']); $name = mb_ereg_replace('[-]+', '-', $name); $parts = pathinfo($name); if (empty($name) || empty($parts['extension'])) < $error = 'Недопустимый тип файла'; >elseif (!empty($allow) && !in_array(strtolower($parts['extension']), $allow)) < $error = 'Недопустимый тип файла'; >elseif (!empty($deny) && in_array(strtolower($parts['extension']), $deny)) < $error = 'Недопустимый тип файла'; >else < // Перемещаем файл в директорию. if (move_uploaded_file($file['tmp_name'], $path . $name)) < // Далее можно сохранить название файла в БД и т.п. $success = '

Файл «' . $name . '» успешно загружен.

'; > else < $error = 'Не удалось загрузить файл.'; >> > > // Вывод сообщения о результате загрузки. if (!empty($error)) < $error = '

' . $error . '

'; > $data = array( 'error' => $error, 'success' => $success, ); header('Content-Type: application/json'); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit();

Источник

jQuery AJAX загрузка файлов на сервер

Как загружать любые файлы, например, картинки на сервер с помощью AJAX и jQuery? Делается это довольно просто! И ниже мы все обстоятельно разберем. В те «древние» времена, когда еще не было jQuery, а может он был, но браузеры были не так наворочены, загрузка файла на сайт с помощью AJAX была делом муторным: через всякие костыли вроде iframe. Я то время не застал, да и кому это теперь интересно. А интересно теперь другое — что сохранение файлов на сайт делается очень просто. Даже не обладающий опытом и пониманием, того как работает AJAX, вебмастер, сможет быстро разобраться что-куда. А эта статья ему в помощь. Если подкрепить эти возможности функциями WordPress, то безопасная обработка и загрузка файлов на сервер становится совсем плёвым и даже интересным делом (пример с WordPress смотрите в конце статьи). Однако, как бы все просто не было, нужно заметить, что минимальный опыт работы с файлами и базовые знания в Javascript, jQuery и PHP все же необходимы! Минимум, нужно представлять как загружаются файлы на сервер, как в общих чертах работает AJAX и хоть немного надо уметь читать и понимать код. Описанный ниже метод довольно стабилен, и по сути опирается на Javascript объект new FormData() , базовая поддержка которого есть во всех браузерах. Для более понятного восприятия материала, он разделен на шаги. На этом все, полетели.

Читайте также:  Python requests file name

AJAX Загрузка файлов: общий пример

Начинается все с наличия на сайте input поля типа file . Нет необходимости, чтобы это поле было частью формы (тега ).

Таким образом, у нас есть HTML код с file полем и кнопкой «Загрузить файлы».

Шаг 1. Данные из поля file

Первым шагом, нужно получить данные загружаемых файлов.

При клике на file-поле, появляется окно выбора файлов, после выбора, данные о них сохраняются в input поле, а нам нужно их от туда «забрать». Для этого повесим на событие change JS функцию, которая будет сохранять имеющиеся данные file-поля в JS переменную files :

var files; // переменная. будет содержать данные файлов // заполняем переменную данными, при изменении значения поля file $('input[type=file]').on('change', function()< files = this.files; >);

Шаг 2. Создаем AJAX запрос (по клику)

Данные файлов у нас есть, теперь их нужно отправить через AJAX. Вешаем это событие на клик по кнопке «Загрузить файлы».

В момент клика создаем новый объект new formData() и добавляем в него данные из переменной files . С помощью formData() мы добьемся того, что отправляемые данные будут выглядеть, как если бы мы просто сабмитили форму в браузере.

Далее, из имеющихся данных формы создаем нестандартный AJAX запрос, в котором передаем файлы в стандартном для сервера формате: $_FILES .

Чтобы такой запрос состоялся, в jQuery нужно указать дополнительные AJAX параметры, поэтому привычная функция $.post() не подходит и мы используем более гибкий аналог: $.ajax() .

Два важных дополнительных параметра нужно установить в false:

processData Отключает обработку передаваемых данных. По умолчанию, например, для GET запросов jQuery собирает данные в строку запроса и добавляет эту строку в конец URL. Для POST данных делает другие преобразования. Нам любые изменения исходных данных будут мешать, поэтому отключаем эту опцию. contentType Отключает установку заголовка типа запроса. Дефолтная установка jQuery равна «application/x-www-form-urlencoded . Такой заголовок не предусматривает отправку файлов. Если установить этот параметр в «multipart/form-data» , PHP все равно не сможет распознать передаваемые данные и выведет предупреждение «Missing boundary in multipart/form-data». В общем, проще всего отключить эту опция, тогда все работает!

// обработка и отправка AJAX запроса при клике на кнопку upload_files $('.upload_files').on( 'click', function( event ) < event.stopPropagation(); // остановка всех текущих JS событий event.preventDefault(); // остановка дефолтного события для текущего элемента - клик для тега // ничего не делаем если files пустой if( typeof files == 'undefined' ) return; // создадим объект данных формы var data = new FormData(); // заполняем объект данных файлами в подходящем для отправки формате $.each( files, function( key, value )< data.append( key, value ); >); // добавим переменную для идентификации запроса data.append( 'my_file_upload', 1 ); // AJAX запрос $.ajax(< url : './submit.php', type : 'POST', // важно! data : data, cache : false, dataType : 'json', // отключаем обработку передаваемых данных, пусть передаются как есть processData : false, // отключаем установку заголовка типа запроса. Так jQuery скажет серверу что это строковой запрос contentType : false, // функция успешного ответа сервера success : function( respond, status, jqXHR )< // ОК - файлы загружены if( typeof respond.error === 'undefined' )< // выведем пути загруженных файлов в блок '.ajax-reply' var files_path = respond.files; var html = ''; $.each( files_path, function( key, val )< html += val +'
'; > ) $('.ajax-reply').html( html ); > // ошибка else < console.log('ОШИБКА: ' + respond.data ); >>, // функция ошибки ответа сервера error: function( jqXHR, status, errorThrown ) < console.log( 'ОШИБКА AJAX запроса: ' + status, jqXHR ); >>); >);

Шаг 3. Обрабатываем запрос: загружаем файлы на сервер

Теперь последний шаг: нужно обработать отправленный запрос.

Читайте также:  What is stack frame in java

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

Создадим файл submit.php с таким кодом (предполагается что submit.php лежит в той же папке, где и файл, с которого отправляется AJAX запрос):

 > $data = $done_files ? array('files' => $done_files ) : array('error' => 'Ошибка загрузки файлов.'); die( json_encode( $data ) ); >

Важно! Этот код только показывает как получать и сохранять файлы. В действительности, вам нужно проверить форматы принимаемых файлов, их размер, транслитерировать кириллические названия и возможно делать какие-то еще проверки.

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

Скопируйте содержимое архива на ваш php сервер, зайдите в главную паку (в браузере) и попробуйте загрузить файлы. Так, вы «в живую» увидите что и как работает.

AJAX Загрузка файлов: пример для WordPress

Для WordPress обрабатывать AJAX запрос в разы проще, потому что есть готовые функции, например media_handle_upload().

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

Чтобы код ниже начал работать, его нужно добавить в файл темы functions.php . Далее, создать страницу с ярлыком ajax_file_upload и зайти на эту страницу. В контенте вы увидите форму для добавления файла. Выбираете файлы и проверяете все ли загрузилось.

Это полноценный пример того, как безопасно загрузить файлы на сервер в среде WordPress.

post_name !== 'ajax_file_upload' ) return $text; return $text .= '  '; > // JS код function ajax_file_upload_jscode() < ?>  // обработчик AJAX запроса function ajax_file_upload_callback() < check_ajax_referer( 'uplfile', 'nonce' ); // защита if( empty($_FILES) ) wp_send_json_error( 'Файлов нет. ' ); $post_id = (int) $_POST['post_id']; // ограничим размер загружаемой картинки $sizedata = getimagesize( $_FILES['upfile']['tmp_name'] ); $max_size = 2000; if( $sizedata[0]/*width*/ >$max_size || $sizedata[1]/*height*/ > $max_size ) wp_send_json_error( __('Картинка не может быть больше чем '. $max_size .'px в ширину или высоту. ','km') ); // обрабатываем загрузку файла require_once ABSPATH . 'wp-admin/includes/image.php'; require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/media.php'; // фильтр допустимых типов файлов - разрешим только картинки add_filter( 'upload_mimes', function( $mimes ) < return [ 'jpg|jpeg|jpe' =>'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', ]; > ); $uploaded_imgs = array(); foreach( $_FILES as $file_id => $data )< $attach_id = media_handle_upload( $file_id, $post_id ); // ошибка if( is_wp_error( $attach_id ) ) $uploaded_imgs[] = 'Ошибка загрузки файла `'. $data['name'] .'`: '. $attach_id->get_error_message(); else $uploaded_imgs[] = wp_get_attachment_url( $attach_id ); > wp_send_json_success( $uploaded_imgs ); >
До этого из: AJAX

Источник

Оцените статью