Как загружать файлы асинхронно с помощью jQuery?
Проблема с асинхронной загрузкой файла с использованием 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 ответ(ов)
Вы можете сделать это на чистом 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)
, чтобы загрузка прошла успешно.
Чтобы загрузить файл с помощью 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
для обработки загрузки.
Самый простой и надежный способ, который я использовал в прошлом, — это просто использовать скрытый тег <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.
В качестве еще одного варианта для загрузки файлов через 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 с возможностью контроля процесса в реальном времени.
Решение, которое я нашёл, состоит в том, чтобы указать атрибут target
у <form>
на скрытый iFrame. Затем iFrame может выполнять JavaScript, чтобы уведомить пользователя о том, что заполнение формы завершено (при загрузке страницы).
Как заставить jQuery выполнять синхронный запрос Ajax вместо асинхронного?
Как управлять перенаправлением после вызова jQuery Ajax
Кэширует ли Safari на iOS 6 результаты $.ajax?
Отправка POST-данных с помощью XMLHttpRequest
Дождаться завершения всех Ajax-запросов jQuery?