Красивый скрипт upload изображений отправка. Ajax и PHP. Загрузка изображения на сервер

Загрузка файлов или картинок на сервер является довольно типичной задачей. Но прогресс не стоит на месте и поэтому сейчас конечно же хочется, чтобы загрузка файлов происходила в фоновом режиме. Как правило ранее это можно было реализовать с использованием технологии flash либо iframe. Также многие используют плагины такие как jQuery Form Plugin или Ajax File Upload Plugin или Multiple File Upload Plugin и море других. С появлением объекта FormData все стало значительно проще. FormData() позволяет составить набор данных для отправки на сервер с помощью XMLHttpRequest.

Давайте же попробуем написать свой код без всяких плагинов (ну кроме конечно фреймворка jQuery) для загрузки картинок или файлов на сервер в фоновом режиме. Вообще алгоритм наших действий будет примерно таков: заполняем поля формы данными. Поля могут быть какими угодно, и текст, и текстареа и селект и файлы. При выборе файлов, благодаря нашему коду на jQuery, эти файлы в фоновом режиме будут загружены во временную директорию на сервере, например в “tmp”. Далее при нажатии на кнопку submit формы, данные отправляются серверному скрипту, который эти данные обработает. Представим что это статьи. Переданные данные мы запишем в базу данных с уникальным id. Далее создадим в каталоге “images” директорию c уникальным номером “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 or gif"; } data.append("file-"+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("Ошибка загрузки файлов"); } }); } }) });

Мы пробежались по нескольким основным методам для получения данных и их дальнейшей передаче 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 )