Загрузка файла на сервер с помощью jQuery AJAX

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

Данный способ загрузки файла на сервер средствами AJAX работает только при подключенном jQuery.

Создадим страницу с таким HTML-кодом:


<!DOCTYPE html>
<html lang="ru">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Upload файла на сервер с помощью jQuery-ajax</title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />

        <!--Подключаем наш CSS-->
        <link href="style.css" type="text/css" rel="stylesheet" />

        <!--Подключаем jQuery-->
        <script src="jquery.js"></script>

        <!--Подключаем наш скрипт-->
        <script src="script.js"></script>
    </head>
    <body>
        <!--В action указываем путь до принимающего скрипта, в который будет отправлен файл, так же указываем class "js-upload-file-with-indicator", на который повесим событие "submit", очень рекомендую каждому классу, на который будет вешаться какое-либо событие (click, submit, mouseover и т.д.), делать префикс "js-", что бы было сразу видно, что данный объект обрабатывается на JS-->
        <form action="ajax.php" class="js-upload-file-with-indicator">
            <!--Индикатор загрузки-->
            <div class="indicator">
                <!--progress-bar-->
                <div class="progress"></div>
                <!--Вывод числового значения загрузки файла в %-->
                <div class="percent"></div>
            </div>
            <div>
                Файл:
            </div>
            <div>
                <input type="file" name="file" />
            </div>
            <div>
                <button type="submit">Загрузить</button>
            </div>
        </form>
    </body>
</html>

Код нашего script.js будет выглядеть так:


$(document).ready(function(){//Запускаем только когда прогрузилась страница
    $(document).on('submit', '.js-upload-file-with-indicator', function(e){//Вешаем на форму событие "submit"
        e.preventDefault();//Запрещаем стандартную отправку формы
        let jqForm = $(this);//jQuery-обект формы

        let jqIndicator = jqForm.find('.indicator');//jQuery-обект индикатора
        jqIndicator.addClass('active').removeClass('error').removeClass('success');//Делаем индикатор видимым и убираем классы, которые могли быть повешены при удачных или неудачных предыдущих отправках

        let jqProgress = jqIndicator.find('.progress');//jQuery-обект ползунка
        let jqPercent = jqIndicator.find('.percent');//jQuery-обект численного значения загрузки в %
        jqPercent.html('');//Очищаем численное значение загрузки

        //Отправляем форму AJAX-ом
        $.ajax({
            type: 'POST',//Обязательно тип запроса "POST"
            url: jqForm.attr('action'),//Путь к принимающему файл скрипту
            data: new FormData(jqForm.get(0)),//Данные формы которые отправляем
            dataType: "html",//Данные, которые ожидает получить наш AJAX-запрос, сейчас это просто HTML, можно указать JSON, если ответ будет в виде JSON-массива
            contentType: false,//Обязательно false
            processData: false,//Обязательно false
            xhr: function() {//Вот тут и вычисляется % загрузки, если progress bar не нужен, то просто не используем элемент xhr
                let xhr = new window.XMLHttpRequest();
                xhr.upload.addEventListener("progress", function(evt){
                    if (evt.lengthComputable) {
                        let percent = 100 * evt.loaded / evt.total;
                        jqProgress.css({'width': percent + '%'});//Передвигаем ползунок загрузки
                        jqPercent.html(Math.round(percent) + '%');//Указываем в % сколько уже загрузилось
                    }
               }, false);
               return xhr;
            },
            success: function(html) {//При удачной отправке
                jqPercent.html('OK');//Прописываем OK вместо численного значения загрузки
                jqIndicator.addClass('success');//Подсвечиваем зеленым цветом с помощью класса .success
            },
            error: function(html) {//При неудачной отправке
                jqPercent.html('ERROR');//Прописываем ERROR вместо численного значения загрузки
                jqIndicator.addClass('error');//Подсвечиваем красным цветом с помощью класса .error
            }
        });
    });
});

Код нашего style.css будет выглядеть так:


/*Форма*/
.js-upload-file-with-indicator {
    position: relative;
    margin: 30px 0 0 0;
}
/*Стилизуем индикатор загрузки*/
.indicator {
    display: none;
    position: absolute;
    border: 1px solid #000;
    width: 300px;
    height: 13px;
    left: 0;
    top: -15px;
}
/*В начале делаем его скрытым*/
.indicator.active {
    display: block;
}
/*ползунок загрузки*/
.progress {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    background-color: #0a0;
    width: 0;
}
/*Численное значение в %*/
.percent {
    position: absolute;
    left: 100%;
    top: 0;
    font-size: 12px;
    line-height: 1;
    padding: 0 0 0 10px;
}
/*При удачной загрузке подсветим зеленым цветом*/
.indicator.success .percent {
    color: #0a0;
}
/*При неудачной загрузке подсветим красным цветом*/
.indicator.error .progress {
    background-color: #f00;
}
.indicator.error .percent {
    color: #f00;
}

Код нашего ajax.php (скрипта, который принимает загружаемый файл) будет выглядеть так:

<?
if(
    (!isset($_FILES['file']['error']) || $_FILES['file']['error'] === 0) &&//Проверка что upload файла прошел без ошибок
    isset($_FILES['tmp_name']) &&//Присутствует путь до загруженного файла
    $_FILES['tmp_name'] &&//Путь до файла не пустой
    file_exists($_FILES['tmp_name'])//Загруженный файл существует
) {
    //$_FILES['tmp_name'] - тут будет лежать абсолютный путь до загруженного файла
}
?>
Рабочий пример загрузки файла через jQuery AJAX

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

Теги: Файл, jQuery, Ajax, upload