Загрузка файлов средствами AJAX
Прежде всего, нужно сразу сказать, что отправить (загрузить) на сервер файл с помощью AJAX нельзя, поэтому приходится прибегать к некоторым хитростями, а конкретно - использовать скрытый фрейм iframe.
Итак, мы создаем скрытый фрейм iframe, и в атрибуте target тега form указываем имя этого фрейма. Отправка файла будет выполнена обычным способом. Но с точки зрения посетителя загрузка будет выглядеть асинхронной - страница, которую он видит, перезагружена не будет.
onsubmit="document.getElementById('res').innerHTML=''; document.getElementById('loading').style.display='block';
return true;">
<input type="file" name="userfile" />
<input type="submit" value="Загрузить" />
</form>
<div id="res" style="margin: 1em 0"></div>
<div id="loading" style="display:none; position: absolute; z-index: 99; left: 45%; top: 45%;">
<img src="/loading.gif" border="0" /> Идет загрузка...
</div>
<iframe id="hiddenframe" name="hiddenframe" style="width:0; height:0; border:0"></iframe>
Работает это так - при нажатии на кнопку submit на экране появляется изображение “loading” (загрузка), потом идет отправка формы. Когда файл загрузился, мы убираем изображение загрузки и выводим на основную страницу сообщение с результатами.
// ...............................................
sleep(5);
echo '<script type="text/javascript">';
echo 'window.parent.document.getElementById("loading").style.display="none";';
// Если загрузка прошла успешно
if (empty($error)) {
echo 'window.parent.document.getElementById("res").innerHTML="Файл успешно загружен";';
} else {
echo 'window.parent.document.getElementById("res").innerHTML="Ошибка при загрузке файла";';
}
echo '</script>';
?>
Серверный скрипт upload.php создает текстовую строку, содержащую обычный JavaScript код. Когда ответ сервера будет загружен во фрейм, код будет автоматически выполнен.
valenok:
Слово ajax, как и сама технология к статье отношений не имеет. Просто отправка файла без перезагрузки страницы.
26 Сентябрь 2008, 22:22admin:
valenok, справедливое замечание: заметку стило бы озаглавить “Асинхронная загрузка файлов” или что-то в этом духе.
27 Сентябрь 2008, 13:30danko-13:
Абсолютно согласен с предыдущим комментатором. Вообще, блог - полное г… Посмотрел на 3 рандомно на 3 странички - пипец!!!
30 Октябрь 2008, 0:05Более-менее знающий кодер здесь ничего нового не найдет, а новичкам тем более непонятно ничего. Вспомни себя, автор, в самом начале изучения Web-технологий и ответь: Что реально полезного дает твой блог?
caesar:
То что говорит danko-13 полный бред, определенные интересные вещи в блоге есть. И надо иметь ввиду что блог делается не для всех подряд, а в основном для автора) Если автор удовлетворен и ему все нравится значит он все делает правильно. Если его труд пригодится кому то еще вдвойне приятно. Если для тебя нет ни чего полезного можно не читать и обратится к другим источникам.
30 Октябрь 2008, 17:14Александр:
нормально! я вот уже не начинающий но еще не профи…есть что интиресного.
30 Октябрь 2008, 19:39Лексеич:
Автору спасибо, кое-что вынес для себя
danko-13: убей себя об стену и схорони останки
2 Ноябрь 2008, 1:38Прим Палвер:
Если у браузера яваскрипт отключен, как будет вести себя субмит? Перезагрузит страницу или проигнорирует нажатие?
9 Ноябрь 2008, 21:47admin:
Прим Палвер, думаю, файл будет загружен, только надписи “Идет загрузка” и сообщения о результатате загрузки мы не увидим. Потому как это делается средствами JavaScript.
10 Ноябрь 2008, 10:40Вадим:
В данном случие AJAX не используется
21 Ноябрь 2008, 14:54frf:
А куда файл загружается?
16 Декабрь 2008, 18:16admin:
frf, туда же, куда всегда - во временную директорию, определяемую директивой upoad_tmp_dir файла php.ini:
17 Декабрь 2008, 11:01Загрузка файлов на сервер
Чтобы сохранить этот файл мы должны его скопировать куда-нибудь, потому что после окончания работы скрипта файл в директории upoad_tmp_dir будет автоматически удален.
Pepper:
Попробуйте пропустить такой код через HTML валидатор, установив doctype XHTML 1.0 Strict.
Валидатор ругнется на аттрибут target и на наличие фреймов. Прием работающий, но корявый.
Обход данной проблемы: создавайте iframe динамически. Если уж используете мощь JavaScript, то ипользуйте ее во всю, а не только для украшения дома на неровном фундаменте.
23 Декабрь 2008, 21:36admin:
Pepper, вы не находите, что предложенный вами способ тоже несколько корявый? Допустим, мы создадим валидный XHTML-документ, а потом с помощью JavaScript добавим iframe, тем самым сделав его невалидым. Получается, решение проблемы в том, чтобы обмануть валидатор?
23 Декабрь 2008, 21:56Pepper:
Нет, я не считаю этот способ корявым, ничуть.
Если использовать предложенную мной идею, боты поисковиков не будут спотыкаться на вставленных в HTML iframe’ах, так как они игнорируют JavaScript.
Я предпочитаю “обмануть” валидатор в случаях, где другого выхода просто нет. А это именно такой случай. Если уж мудрите с “ajax” загрузкой, то можно сделать это и красиво.
9 Январь 2009, 18:54Aube:
Статья названа правильно - AJAX это не только XMLHttpRequest. Хоть вики почитайте, прежде чем пороть чушь.
А валидность документов вообще ерунда - к примеру проверьте гугл, яндекс на валидность
И тем более не стоит усложнять логику страницы скриптами для того чтобы соответствовать рекоменованным, но вовсе не обязательным стандартам.
Автору за статью спасибо - помогла.
17 Январь 2009, 7:43Pepper:
Aube, есть право выбора. Лепите страницы как хочется, кто ж не мешает.
20 Январь 2009, 7:19Только стоит подумать о кроссбраузерности прежде.
Стандарты они для того и стандарты, хоть и не на 100% поддерживаются всеми браузерами.
Красун:
Технология называется comet. Но в силу привычку, мы называем подобные вещи и решения AJaX.
20 Февраль 2009, 6:14Zoomanoid:
Отличный способ обойти проблему перезагрузки страницы у пользователя при применеия Ajax и
загрузить файл стандартным образом. А есть ли пример загрузки файла с применением XMLHttpRequest и есть ли там скрытые проблемы?
Автору за статью спасибо.
5 Март 2009, 4:25А за готовность вести такой блог - большое спасибо.
admin:
Zoomanoid, в статье XMLHTTPRequest: описание, применение, частые проблемы я встретил вот такие слова:
5 Март 2009, 10:35Возможности XmlHttpRequest позволяют создать запрос с любым телом. Например, можно вручную сделать POST-запрос, загружающий на сервер файл. Функционал создания таких запросов есть, в частности, во фреймворке dojo. Но можно реализовать его и самому, прочитав о нужном формате тела POST и заголовках.
Но сам я такого не делал - так что рассказать не смогу. И этому есть причины. Насколько я понимаю, загрузить файл с применением только XMLHttpRequest невозможно: в JavaScript отсутствует возможность прямой работы с локальными файлами. Т.е., сделать сам POST с помощью XMLHTTPRequest можно, но вот считать локальный файл в какую-нибудь переменную JavaScript - нет. Это сделано с целью обеспечения безопасности.
Zoomanoid:
Спасибо за ясность с локальными файлами.
6 Март 2009, 6:44Не смог приспособить Ваш вполне рабочий пример для своих нужд, так как не смог с его помощью организовать обработку результатов выгрузки.
Благодаря Вашему блогу нашел рабочее (после мелких исправлений) решение своей проблемы с
использованием iframe. http://web-tec.info/
SorokinWS:
Большое спасибо, за интересную идею. В моём случае, это действительно оказалось выходом. Блог в целом не смотрел, но если тут много подобных штук, то буду захаживать.
29 Апрель 2009, 18:22Константин:
valenok, тем не меннее все известные AJAX библиотеки по такому принципу и работают. Нужно запомнить что НЕТ ВОЗМОЖНОСТИ С ПОМОЩЬЮ JAVA SCRIPT ОТПРАВИТЬ ФАЙЛ. Слово AJAX сдесь я думаю применимо. Т.к. с помощью Java Script возвращается результат.
5 Май 2009, 13:05Роман:
Очень полезная статья оказалась. И зря на нее гнали вначале - достаточно просто и доходчиво написано. Спасибо автору!
23 Июнь 2009, 21:30Дархан:
Отличная статья! Самое главное код рабочий. Взял, поставил себе - осталось только доработать под свои нужды. К слову ajax вообще не знаю
5 Июль 2009, 21:45Констан:
Кто тут критиковал насчет невалидности. Если так боитесь поисковиков, заключайте этот фрагмент в ноиндекс и прочие подобные вещи.
12 Июль 2009, 7:06haZe:
Хмм, интересное решение, понравилось. А окончание загрузки определять по readyState?
14 Август 2009, 23:10А не найдется такое же решение, нос мультизагрузкой, т.е. выделять кучу файлов и чтоб они загружались.
Да и вопрос на счет уязвимости, я слышал сайт как то через фреймы легко сломать, но еще не сталкивался с подробной информацией.
Поклон за отличную идею!
admin:
А окончание загрузки определять по readyState?
15 Август 2009, 7:33В заметке написано, что к AJAX (асинхронная отправка данных на сервер) этот способ не имеет отношения. Так что какой readyState?
выделять кучу файлов и чтоб они загружались
А кто мешает сделать форму с несколькими полями загрузки файлов?
Вопрос:
Вопрос, загрузка то происходит, но как потом получить информацию о загруженном файле и переместить его куда надо?
20 Август 2009, 12:36admin:
как потом получить информацию о загруженном файле
20 Август 2009, 13:17Из массива $_FILES: Загрузка файлов на сервер
и переместить его куда надо
move_uploaded_file()
Devoter:
Статья больше напоминает собственные записки из разряда “чтобы не забыть”, но уж никак не полезный интернет-ресурс. Зря потратил время на прочтение статьи (любой человек, немного понимающий в логике и web-программировании сам до этого дойдет), особенно, если учесть тот факт, что средствами ajax МОЖНО загрузить файл на сервер (и при том - не один!).
24 Август 2009, 0:02