31

Как загружать файлы асинхронно с помощью jQuery?

21

Проблема с асинхронной загрузкой файла с использованием jQuery

Я хотел бы реализовать асинхронную загрузку файла с помощью jQuery. Вот мой код:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Данные загружены: ");
            }
        });
    });
});

И HTML-код выглядит так:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>Файл</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Загрузить"/>

Проблема в том, что вместо загрузки файла я получаю только имя файла. Как я могу решить эту проблему?

5 ответ(ов)

0

Вы можете сделать это на чистом JavaScript достаточно легко. Вот фрагмент кода из моего текущего проекта:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position / e.totalSize) * 100; // Рассчитываем процент загрузки
    // Здесь можно отрисовать красивую индикатор загрузки
};
xhr.onreadystatechange = function(e) {
    if (this.readyState === 4) {
        // Обработка завершения загрузки файла
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName', file.name); // Передаем имя файла
xhr.send(file);

Этот код создает объект XMLHttpRequest, который позволяет отслеживать прогресс загрузки файла и обрабатывать завершение. Убедитесь, что вы передаете нужный файл в xhr.send(file), чтобы загрузка прошла успешно.

0

Чтобы загрузить файл с помощью jQuery, вы можете использовать метод .ajax(). Вот пример кода, который показывает, как это сделать:

HTML:

<form id="upload-form">
    <div>
        <label for="file">Файл:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Отправить" />
</form>

CSS:

.progress { display: none; }

JavaScript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault(); // предотвращаем стандартное поведение формы

        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show(); // показываем индикатор загрузки

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete); // обновляем прогресс

                        if (percentComplete === 100) {
                            progress.hide().val(0); // скрываем индикатор, когда загрузка завершена
                        }
                    }
                };

                return xhr; // возвращаем объект XMLHttpRequest
            },
            url: 'upload.php', // указываем URL для загрузки
            type: 'POST', // метод отправки
            data: new FormData(this), // создаем объект FormData с текущей формой
            contentType: false, // отключаем автоматическую установку заголовка contentType
            cache: false, // отключаем кэширование
            processData: false, // отключаем обработку данных
            success: function(data, status, xhr) {
                // обработка успешного ответа
            },
            error: function(xhr, status, error) {
                // обработка ошибки
            }
        });
    }));
});

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

0

Самый простой и надежный способ, который я использовал в прошлом, — это просто использовать скрытый тег <iframe> с вашей формой. Это позволит отправить данные формы внутри iframe без перезагрузки страницы.

Это если вы не хотите использовать плагин, JavaScript или какие-либо другие формы «магии», кроме HTML. Конечно, вы можете комбинировать это с JavaScript или чем-то еще...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none"></iframe>

Вы также можете прочитать содержимое iframe в событии onLoad, чтобы получить сообщения об ошибках сервера или успешные ответы и затем вывести их пользователю.

Chrome, iFrames и onLoad

-примечание- вам нужно продолжать читать, только если вы заинтересованы в том, как настроить блокировку интерфейса при загрузке/выгрузке

В настоящее время Chrome не вызывает событие onLoad для iframe, когда он используется для передачи файлов. Firefox, IE и Edge все вызывают событие onload для передачи файлов.

Единственное решение, которое я нашел для Chrome, заключалось в использовании cookie.

Для этого, собственно, когда начинается загрузка/выгрузка:

  • [Клиентская сторона] Начните интервал для проверки существования cookie
  • [Серверная сторона] Выполните все необходимые действия с данными файла
  • [Серверная сторона] Установите cookie для клиентского интервала
  • [Клиентская сторона] Интервал видит cookie и использует его как событие onLoad. Например, вы можете запустить блокировщик интерфейса, а затем при срабатывании onLoad (или когда cookie установлено) убрать блокировщик интерфейса.

Использовать cookie для этого неэстетично, но это работает.

Я создал плагин jQuery, чтобы решить эту проблему для Chrome при выгрузке, вы можете найти его здесь:

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

Тот же основной принцип применяется и к загрузке.

Чтобы использовать загрузчик (включите JS, очевидно):

$('body').iDownloader({
    "onComplete": function() {
        $('#uiBlocker').css('display', 'none'); // скрыть блокировщик интерфейса по завершении
    }
});

$('somebutton').click(function() {
    $('#uiBlocker').css('display', 'block'); // заблокировать интерфейс
    $('body').iDownloader('download', 'http://example.com/location/of/download');
});

А на серверной стороне, непосредственно перед передачей данных файла, создайте cookie:

setcookie('iDownloader', true, time() + 30, "/");

Плагин увидит cookie и.trigger onComplete callback.

0

В качестве еще одного варианта для загрузки файлов через Ajax, вы можете рассмотреть библиотеку Simple Ajax Uploader:

Ссылка на репозиторий

Вот некоторые ключевые особенности:

  • Кроссбраузерность — работает в IE7+, Firefox, Chrome, Safari, Opera.
  • Поддержка множественной загрузки — поддерживает множество параллельных загрузок, даже в браузерах без HTML5.
  • Нет флеша или внешнего CSS — всего один файл JavaScript размером 5 Кб.
  • Необязательная поддержка прогресс-баров — имеется встроенная поддержка кроссбраузерных индикаторов загрузки (с использованием PHP-расширения APC).
  • Гибкость и высокая настраиваемость — вы можете использовать любой элемент в качестве кнопки загрузки и стилизовать собственные индикаторы прогресса.
  • Не нужны формы — достаточно предоставить элемент, который будет служить кнопкой загрузки.
  • Лицензия MIT — можно бесплатно использовать в коммерческих проектах.

Пример использования:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // кнопка загрузки
    url: '/uploadhandler', // URL серверной обработки загрузки
    name: 'userfile', // название параметра загружаемого файла
    onSubmit: function() {
        this.setProgressBar($('#progressBar')); // назначаем элементом наш индикатор прогресса
    },
    onComplete: function(file, response) {
        // выполняем необходимые действия после завершения загрузки
    }
});

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

0

Решение, которое я нашёл, состоит в том, чтобы указать атрибут target у <form> на скрытый iFrame. Затем iFrame может выполнять JavaScript, чтобы уведомить пользователя о том, что заполнение формы завершено (при загрузке страницы).

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь