Jq ajax плагин загрузка файлов. Ajax и PHP. Загрузка изображения на сервер. Асинхронная загрузка файлов в WebAPI

Наверное многие сталкивались с вопросом "Как загрузить файл на сервер с помощью JS и JQuery?".
И вероятно не у всех получилось это сделать. На самом деле все не так сложно как кажется.
В данном уроке я опишу процесс загрузки файла на сервер(хостинг) .
Для обмена данными между браузером и веб-сервером, используется технология ajax.
Версия JQuery используемая в рецепте: 2.2.2.

Создаем примитивную разметку из тегов html, head и body.
В теге head необходимо прописать путь до библиотеки jquery.
В примере я использую jquery с сервера google.

В теге body создаем форму, которая состоит из тега input и button.
С помощью input type="file" осуществляется выбор файла для загрузки.
Тег button необходим для запуска js кода на передачу файла.

Форме задаем name="uploader", enctype="multipart/form-data", method="POST".
Имя формы: name="uploader"
Способ кодирования данных формы: enctype="multipart/form-data"
Метод передачи данных: method="POST"

Отправить этот файл: Загрузить

Весь код html и js разметки:
Отправить этот файл: Загрузить

Переходим к java script коду.
Для передачи файла необходимо передавать форму целиком:
$("form").submit(function(e) {

Считываем данные формы в переменную:
var formData = new FormData($(this));

Далее для передачи данных на веб-сервер используем технологию ajax.
В случае успешной передачи файла во всплывающем окне будет отображено соответствующее сообщение.
В случае возникновения ошибки или отсутствии файла будет отображено сообщение с текстом возникшей проблемы.
$.ajax({ url: "file.php", type: "POST", data: formData, async: false, success: function (msg) { alert(msg); }, error: function(msg) { alert("Ошибка!"); }, cache: false, contentType: false, processData: false });

Весь код на java script с использование jquery:

Теперь остался код на стороне сервера для приема данных с формы методом POST запроса.

Получаем корневую директорию сайта и назначаем папку для загрузки файлов:
$uploaddir = $_SERVER["DOCUMENT_ROOT"].DIRECTORY_SEPARATOR."uploads".DIRECTORY_SEPARATOR;

Считываем загружаемый файл:
$uploadfile = $uploaddir . basename($_FILES["userfile"]["name"]);

Проверяем загружен ли файл.
В соответствии с входящими данными назначаем сопровождающее сообщение.
Если файл не загружен, загружаем в директорию указанную в $uploadfile:
if (move_uploaded_file($_FILES["userfile"]["tmp_name"], $uploadfile)) { $out = "Файл корректен и был успешно загружен.\n"; } else { $out = "Возможная атака с помощью файловой загрузки!\n"; }

При выполнении указанных действий возвращается ответ.

Весь код на php:

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

Отправить этот файл: Загрузить $("form").submit(function(e) { var formData = new FormData($(this)); $.ajax({ url: "file.php", type: "POST", data: formData, async: false, success: function (msg) { alert(msg); }, error: function(msg) { alert("Ошибка!"); }, cache: false, contentType: false, processData: false }); e.preventDefault(); });

Скачать файл с исходным кодом:

В наше время веб-сайты становятся все более интерактивными. Это касается не только специализированных сервисов, но и обычных интернет магазинов, блогов и небольших сайтов. Основной особенностью является асинхронный 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 = 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 , составить и выполнить такой запрос не вызовет у вас никаких проблем.

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

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

В сети существует множество библиотек реализующих загрузку файлов на сервер. Так что у разработчика есть широкий выбор каким инструментом можно воспользоваться. Но порой они довольно сложные для новичком. Изначально для статьи было решено написать простую библиотеку, которую будет легко понять. Но по счастью в сети была найдена довольно простая реализация загрузки фалов, которой было и решено воспользоваться. Называется она dmuploader и является плагином для jQuery.

С помощью dmuploader мы создадим загрузчик, похожий по дизайну на тот, что реализован в wordpress. С Drag And Drop’ом и кликами! Преступим!

Структура проекта:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #dropzone { border : 4px dashed #bbb ; border-radius : 5px ; color : #444 ; padding : 25px ; text-align : center ; } #dropzone .title { font-size : 20px ; } #dropzone input { -moz-border-bottom-colors: none ; -moz-border-left-colors: none ; -moz-border-right-colors: none ; -moz-border-top-colors: none ; border-color : transparent ; border-image: none ; cursor : pointer ; direction : ltr ; margin : 0 ; opacity: 0 ; position : absolute ; right : 0 ; top : 0 ; transform: translate(-300px , 0px ) scale(4 ) ; } #dropzone .browser span { background : #f7f7f7 ; border : 1px solid #ccc ; color : #555 ; cursor : pointer ; font-size : 16px ; height : 46px ; line-height : 44px ; padding : 0 36px ; } #dropzone .browser span:hover { border : 1px solid #999 ; }

Javascript:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 // index.php $(document) .ready (function () { $("#dropzone" ) .dmUploader ({ url: "upload.php" , dataType: "json" , maxFileSize: 256 * 1014 , allowedTypes: "image/*" , onBeforeUpload: function (id) { $) .show () ; } , onUploadSuccess: function (id, response) { $("div#output" ) .html ("" ) ; } , onUploadError: function (id, message) { $.jGrowl ("Файл: " + id + " не загрузился: " + message, { theme: "error" } ) ; } , onFileTypeError: function (file) { $.jGrowl (, { theme: "error" } ) ; } , onFileSizeError: function (file) { $.jGrowl ("Файл слишком большой!!" , { theme: "error" } ) ; } , onFallbackMode: function (message) { $.jGrowl ("Ваш браузер не поддерживается 8(" , { theme: "error" } ) ; } } ) ; } ) ;

Все! Клиенсткая часть готова. Немного подробнее:

  • DmUploader за нас подпишется на события drag для дом элемента #dropzone, а также на событие change для элемента input file.
  • При наступлении одного из событий, будет прочитан локальный файл с помощью file api.
  • У файла будет проверен размер и тип. В нашем случае, только картинки.
  • Удовлетворяющий всем проверкам файл будет загружен на сервер.
  • В процессе работы будут вызываться соответствующие коллбэки (callbacks). Например, onUploadSuccess вызовется после успешной загрузки файла. Вторым аргументом в функцию поступит ответ от сервера в формате json. Коллбэков у библиотеки больше, чем представлено в примере. С помощью них можно реализовать более сложные задачи.
  • Сервер

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 // upload.php require_once __DIR__ . "/protected/bootstrap.php" ; if (! IS_POST() || ! $_FILES ) { stopAndResponseMessage("error" , "Только POST, FILES" } $files = convertFileInformation($_FILES ) ; if (! isset ($files [ "file" ] ) ) { stopAndResponseMessage("error" , "Файл не загружался" ) ; } $file = $files [ "file" ] ; if ($file [ "error" ] !== UPLOAD_ERR_OK) { stopAndResponseMessage( "error" , uploadCodeToMessage($file [ "error" ] ) ) ; } $mimeType = guessMimeType($file [ "tmp_name" ] ) ; if (! $mimeType ) { stopAndResponseMessage("error" , "Тип файла не распознается!" ) ; } $validMimeType = [ "image/png" , "image/jpeg" ] ; if (! in_array ($mimeType , $validMimeType ) ) { stopAndResponseMessage( "error" , "Загружать можно только png и jpeg!" ) ; } $size = filesize ($file [ "tmp_name" ] ) ; if ($size > 256 * 1024 ) { stopAndResponseMessage("error" , "Файл слишком большой!!" ) ; } $uploadDir = __DIR__ . "/files" ; if (! is_writable ($uploadDir ) ) { stopAndResponseMessage( "error" , "Папка для файлов не доступна для записи." ) ; } $filename = time () . "-" . mt_rand (0000 , 9999 ) . "." . guessFileExtension($mimeType ) ; if (! move_uploaded_file ( $file [ "tmp_name" ] , $uploadDir . "/" . $filename ) ) { stopAndResponseMessage("error" , "Файл не был перемецен!" ) ; } sendResponse("upload" , [ "url" => "files/" . $filename ] ) ;

    Стоит заострить особое внимание на функции guessMimeType. Она с помощью расширения FileInfo определяет MIME тип файла. Как видно из кода, тип и размер файла, присланные от браузера не определяются при проверке. Их может подделать злоумышленник.

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //protected/inc/func.php function guessMimeType($path , $magicFile = null ) { if (! is_file ($path ) ) { return null ; } if (! is_readable ($path ) ) { return null ; } if (! $finfo = new \finfo(FILEINFO_MIME_TYPE, $magicFile ) ) { return ; } return $finfo -> file ($path ) ; }

    На основе демо вы можете углубить свои знания в этой области. В исходных кодах даны ссылки для дальнейшего изучения. Эксперементируйте!

    Наверное многие сталкивались с вопросом "Как загрузить файл на сервер с помощью JS и JQuery?".
    И вероятно не у всех получилось это сделать. На самом деле все не так сложно как кажется.
    В данном уроке я опишу процесс загрузки файла на сервер(хостинг) .
    Для обмена данными между браузером и веб-сервером, используется технология ajax.
    Версия JQuery используемая в рецепте: 2.2.2.

    Создаем примитивную разметку из тегов html, head и body.
    В теге head необходимо прописать путь до библиотеки jquery.
    В примере я использую jquery с сервера google.

    В теге body создаем форму, которая состоит из тега input и button.
    С помощью input type="file" осуществляется выбор файла для загрузки.
    Тег button необходим для запуска js кода на передачу файла.

    Форме задаем name="uploader", enctype="multipart/form-data", method="POST".
    Имя формы: name="uploader"
    Способ кодирования данных формы: enctype="multipart/form-data"
    Метод передачи данных: method="POST"

    Отправить этот файл: Загрузить

    Весь код html и js разметки:
    Отправить этот файл: Загрузить

    Переходим к java script коду.
    Для передачи файла необходимо передавать форму целиком:
    $("form").submit(function(e) {

    Считываем данные формы в переменную:
    var formData = new FormData($(this));

    Далее для передачи данных на веб-сервер используем технологию ajax.
    В случае успешной передачи файла во всплывающем окне будет отображено соответствующее сообщение.
    В случае возникновения ошибки или отсутствии файла будет отображено сообщение с текстом возникшей проблемы.
    $.ajax({ url: "file.php", type: "POST", data: formData, async: false, success: function (msg) { alert(msg); }, error: function(msg) { alert("Ошибка!"); }, cache: false, contentType: false, processData: false });

    Весь код на java script с использование jquery:

    Теперь остался код на стороне сервера для приема данных с формы методом POST запроса.

    Получаем корневую директорию сайта и назначаем папку для загрузки файлов:
    $uploaddir = $_SERVER["DOCUMENT_ROOT"].DIRECTORY_SEPARATOR."uploads".DIRECTORY_SEPARATOR;

    Считываем загружаемый файл:
    $uploadfile = $uploaddir . basename($_FILES["userfile"]["name"]);

    Проверяем загружен ли файл.
    В соответствии с входящими данными назначаем сопровождающее сообщение.
    Если файл не загружен, загружаем в директорию указанную в $uploadfile:
    if (move_uploaded_file($_FILES["userfile"]["tmp_name"], $uploadfile)) { $out = "Файл корректен и был успешно загружен.\n"; } else { $out = "Возможная атака с помощью файловой загрузки!\n"; }

    При выполнении указанных действий возвращается ответ.

    Весь код на php:

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

    Отправить этот файл: Загрузить $("form").submit(function(e) { var formData = new FormData($(this)); $.ajax({ url: "file.php", type: "POST", 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” директорию 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("Ошибка загрузки файлов"); } }); } }) });