Пишемо код завантаження зображення через ajax. Завантаження файлу на сервер за допомогою JavaScript та бібліотеки JQuery

В наш час веб-сайти стають все більш інтерактивними. Це стосується не лише спеціалізованих сервісів, але і звичайних інтернетмагазинів, блогів та невеликих сайтів. Основною особливістю є асинхронний 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 Ajax Upload Image upload Image file:

Звичайна 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; // Генеруємо нове ім'я зображення. Можна зберегти і зі старим // але це не рекомендується робити $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) ( var reader = new FileReader(); reader.onload = function (e) ( $( "#preview").attr("src", e.target.result); ) reader.readAsDataURL(input.files); ) ) 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 = новий 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, скласти та виконати такий запит не викличе у вас жодних проблем.

Власне, на цьому закінчимо. Зображення завантажується, сторінка не перезавантажується, всі задоволені. Якщо у вас виникають запитання чи пропозиції, пишіть коментарі.

Хорошого дня та успіхів 🙂

Ми пробіглися кількома основними методами для отримання даних та їх подальшої передачі AJAX-запитом. Тепер настав час поговорити про те, як можна завантажувати файли за допомогою AJAX . Ще донедавна, способів завантажувати файли без перезавантаження самої сторінки, було не так вже й багато (прихований iframe, Flash). Вони і зараз використовуються через те, що ще залишаються користувачі зі старими версіями браузерів, яких не торкнувся прогрес. Але озиратися назад не будемо, тому крокуємо в ногу з часом.

Розглянемо, на мій погляд, один із самих зручних способівдля роботи з файлами (і не тільки) – об'єкт FormData . Нехай буде така простенька форма для завантаження аватара користувача:

HTML ( файл index.html)

П.І.Б:
Аватар:

Перейдемо до JS-частини. З полем "П.І.Б." складнощів не буде і його використовуємо тільки для наочності того, що разом з файлом, ми можемо відправляти будь-які інші дані.

jQuery ( файл script.js)

$(function()( $("#my_form").on("submit", function(e)( e.preventDefault(); var $that = $(this), formData = new FormData($that.get( 0));// створюємо новий екземпляр об'єкта і передаємо йому нашу форму (*) $.ajax(( url: $that.attr("action"), type: $that.attr("method"), contentType: false , // важливо - прибираємо форматування даних за умовчанням processData: false, // важливо - прибираємо перетворення рядків за умовчанням data: formData, dataType: "json", success: function(json)( if(json)( $that.replaceWith( json);)))));)));));

(*)Зверніть увагу на те, що передаємо форму не об'єктом jQuery, а DOM-елемент

PHP-обробник ( файл handler.php)

Весь html кодвключаючи js:

Надіслати цей файл: Завантажити $("form").submit(function(e) ( var formData = new FormData($(this))); data: formData, async: false, success: function (msg) ( alert(msg); ), error: function(msg) ( alert("Помилка!"); ), cache: false, contentType: false, processData: false ));e.preventDefault(); ));

Завантажити файл із вихідним кодом:

Завантаження файлів або картинок на сервер є досить типовим завданням. Але прогрес не стоїть на місці і тому зараз звичайно хочеться, щоб завантаження файлів відбувалося у фоновому режимі. Як правило, раніше це можна було реалізувати з використанням технології flashабо iframe. Також багато хто використовує плагіни такі як jQuery Form Plugin або Ajax File Upload Plugin або Multiple File Upload Plugin та море інших. З появою об'єкта FormData все стало значно простіше. FormData() дозволяє скласти набір даних для відправки на сервер за допомогою XMLHttpRequest.

Давайте спробуємо написати свій код без будь-яких плагінів (ну крім звичайно фреймворку jQuery) для завантаження картинок або файлів на сервер у фоновому режимі. Загалом алгоритм наших дій буде приблизно такий: заповнюємо поля форми даними. Поля можуть бути будь-якими, і текст, і текстареа і селект і файли. При виборі файлів завдяки нашому коду на jQuery ці файли у фоновому режимі будуть завантажені в тимчасову директорію на сервері, наприклад у “tmp”. Далі при натисканні на кнопку submit формидані надсилаються серверному скрипту, який ці дані обробить. Уявімо, що це статті. Надіслані дані ми запишемо в базу даних з унікальним id. Далі створимо в каталозі "images" директорію з унікальним номером "id" і якщо в папці "tmp" у нас були якісь файли ми їх скопіюємо в створену папку "id" після чого очистимо папку "tmp". Резюмуючи: фоном заливаємо картинки в tmp, при сабміті форми записуємо дані в базу, у нас з'явиться унікальний номерзапис. Створюємо папку з цим номером та переміщуємо туди наші файли. Всі. У цій статті заливку в базу та копіювання файлів ми розглядати не будемо. Думаю, тут у кожного буде щось своє. Ми зосередимося на одному – асинхронного завантаженнякартинок (або файлів).

Так ось наш html шматок. Тут звернемо увагу на те, що у нас є гіф-файл з картинкою прелоудером (зациклений гурток), який ми стилями ховаємо від показу. Також полю file надамо id = file, а формі enctype = "multipart / form-data". Ім'я поля file буде file, тобто. щоб ми могли працювати з масивом, якщо у нас дозволено завантаження декількох файлів (атрибут multiple).

#preloader (visibility: hidden;) Додати інформацію

У цій формі у нас крім поля з файлом є ще пара полів для прикладу: input=text. Тобто. перед нами звичайна форманаприклад для адмінки, яка є набором необхідних вам полів. Для початку якщо хочете можете перевірити роботу скрипта, прописавши спочатку файлу рядка показу масиву FILES:

//upload.php print_r($_FILES);

Тепер напишемо наш серверний скрипт, який буде викликатись з допомогою jQuery. Його завдання перекинути залиті файли з тимчасової директорії сервера в нашу, припустимо, як ми вирішили в “tmp”, після чого показати їх.

//upload.php function show_dir($dir) // функція показу картинок з tmp папки ( $list = scandir($dir); unset($list,$list); foreach ($list as $file) ( echo " "; ) ) foreach ($_FILES as $key => $value) ( ​​//переміщення файлів у tmp move_uploaded_file($value["tmp_name"], "tmp/".$value["name"]); ) show_dir( "./tmp/");

А тепер і наш js-скрипт, який у фоновому режимі заллє наші файли на сервер. Все чаклунство буде виконано завдяки об'єкту FormData(). Цей код ми допишемо до кінця нашого index.php перед тегом.

$(document).ready(function()( $("#preloader").hide(); $("#file").bind("change", function()( var data = new FormData(); var error = ""; jQuery.each($("#file").files, function(i, file) ( if(file.name.length)< 1) { error = error + " Файл имеет неправильный размер! "; } //Проверка на длину имени if(file.size >1000000) ( error = error + " File " + file.name + " is to big."; ) //Перевірка розміру файлу if(file.type != "image/png" && file.type != "image/jpg && !file.type != "image/gif" && file.type != "image/jpeg") ( error = error + "File " + file.name + " doesnt match png, jpg or gif"; /Перевірка типу файлів data.append("file-"+i, file); )); if (error != "") ($("#info").html(error);) else ( $.ajax(( url: "upload.php", data: data, cache: false, contentType: false, processData: false, type: "POST", beforeSend: function() ( $("#preloader").show(); ), success: function(data)( $("#info").html(data); $("#preloader").hide(); ) )); ) )) ));

Ну от начебто б і все. Якщо хтось не зрозумів, питайте. Якщо у когось будуть доповнення, теж буду радий!
Порада: якщо ви ще не використовували код для видалення файлів з будь-якої директорії, то рекомендую для тесту поміняти функцію видалення rmdir на echo, щоб переконатися, що будуть видалені тільки ті файли, які ви хочете видалити. Gif прелоадери можна взяти наприклад з мого уроку Як зробити Gif анімацію. Приклади наприкінці статті.

UPD:

Якщо комусь захочеться додати краси, наприклад прогрес бар, то для цього нам треба буде дописати кілька рядків коду. У html шаблонми додамо супер елемент з html5 - progress, а в js код додамо кілька рядків з об'єктом XMLHttpRequest.
І так наш html доповниться наступним:

А в код js допишемо:

Function progressHandlingFunction(e)( if(e.lengthComputable)( $("progress").attr((value:e.loaded,max:e.total)); ) )

Xhr: function() ( var myXhr = $.ajaxSettings.xhr(); if(myXhr.upload)( // перевірка що здійснюється upload myXhr.upload.addEventListener("progress",progressHandlingFunction, false); //передача в функцію значень ) return myXhr; )

Фінальний результат js коду:

$(document).ready(function()( function progressHandlingFunction(e)( if(e.lengthComputable)( $("progress").attr((value:e.loaded,max:e.total)); ) ) $("#preloader").hide(); $("#file").bind("change", function()( var data = new FormData(); var error = ""; jQuery.each($( "#file").files, function(i, file) ( if(file.name.length)< 1) { error = error + " Файл имеет неправильный размер! "; } if(file.size >1000000) ( error = error + " File " + file.name + " is to big."; ) if(file.type != "image/png" && file.type != "image/jpg" && !file. type != "image/gif" && file.type != "image/jpeg") ( error = error + "File " + file.name + " doesnt match png, jpg або gif"; -"+i, file); )); if (error != "") ($("#info").html(error);) else ( $.ajax(( url: "productUploadImg.php", type: "POST", xhr: function() ( var myXhr = $.ajaxSettings.xhr(); if(myXhr.upload)( // перевірка що здійснюється upload myXhr.upload.addEventListener("progress",progressHandlingFunction, false); //передача в функцію значень ) return myXhr; ) , data: data, cache: false, contentType: false, processData: false, beforeSend: function() ( $("#preloader").show(); ), success: function(data)( $("#info" ).html(data); $("#preloader").hide(); ) , error: errorHandler = function() ( $("#info").html("Помилка завантаження файлів"); ))); ))))));