![Blog. Just Blog](/images/logo.png)
Загрузка файлов перетаскиванием в окно браузера
![Загрузка файлов перетаскиванием в окно браузера](/upload/74/9a/749ad31dfdc811ce1b732c0b3f05b881.jpg)
Загрузка файлов перетаскиванием в окно браузера
Практически все современные web-сервисы предлагают пользователям такую фичу, как загрузку файлов простым перетаскиванием их в браузер. Это действительно очень удобно, когда надо загрузить сразу несколько файлов, поле загрузки может иметь произвольный вид и форму, т.к. не подвязано на стандартные элементы формы, и еще множество других плюсов. Как же это сделано? Очень просто. Мы уже рассматривали в одной из статей прием и отправку текстовых данных при помощи технологии AJAX, загрузка файлов выполняется не намного сложнее.
Для начала определим какую-нибудь область на HTML-странице, на которую мы будем перетаскивать файлы. Это очень просто:
Code (HTML) : Убрать нумерацию
- <div class="drag" id="drag">Drop-zone</div>
Code (HTML) : Убрать нумерацию
- <div class="drag" id="drag"
- ondragenter="dropenter(event);" ondragover="dropenter(event);"
- ondragleave="dropleave();" ondrop="return dodrop(event);" >
- Drop-zone
- </div>
Code (JavaScript) : Убрать нумерацию
- // Эффект при наведении курсора с файлами на зону выгрузки
- function dropenter(e) {
- // Подавить событие
- e.stopPropagation();
- e.preventDefault();
- // Визуальный эффект "зоны выгрузки" при заходе на нее курсора
- var tmp=document.getElementById('drag');
- tmp.style.background='#FF0000';
- tmp.innerHTML='Drop your files here';
- }
Code (JavaScript) : Убрать нумерацию
- // Эффект при отпускании файлов или выходе из зоны выгрузки
- function dropleave() {
- // Привести "зону выгрузки" в первоначальный вид
- var tmp=document.getElementById('drag');
- tmp.style.background='#DDDDDD';
- tmp.innerHTML='Drop-zone';
- }
Code (JavaScript) : Убрать нумерацию
- // Проверка и отправка файлов на загрузку
- function dodrop(e) {
- var dt = e.dataTransfer;
- if(!dt && !dt.files) { return false ; }
- // Получить список загружаемых файлов
- var files = dt.files;
- // Fix для Internet Explorer
- dt.dropEffect="copy";
- // Загрузить файлы по очереди, проверив их размер
- for (var i = 0; i < files.length; i++) {
- if (files[i].size<15000000) {
- // Отправить файл в AJAX-загрузчик
- ajax_upload(files[i]);
- }
- else {
- alert('Размер файла превышает допустимое значение');
- }
- }
- // Подавить событие перетаскивания файла
- e.stopPropagation();
- e.preventDefault();
- return false;
- }
Code (JavaScript) : Убрать нумерацию
- // AJAX-загрузчик файлов
- function ajax_upload(file) {
- // Mozilla, Safari, Opera, Chrome
- if (window.XMLHttpRequest) {
- var http_request = new XMLHttpRequest();
- }
- // Internet Explorer
- else if (window.ActiveXObject) {
- try {
- http_request = new ActiveXObject("Msxml2.XMLHTTP");
- }
- catch (e) {
- try {
- http_request = new ActiveXObject("Microsoft.XMLHTTP");
- }
- catch (e) {
- // Браузер не поддерживает эту технологию
- return false;
- }
- }
- }
- else {
- // Браузер не поддерживает эту технологию
- return false;
- }
- var name = file.fileName || file.name;
- // Добавить для файла новую полосу-индикатор загрузки
- var tmp=document.getElementById('upload_overall');
- var new_div = document.createElement("div");
- new_div.className='percent_div';
- tmp.appendChild(new_div);
- // Обработчик прогресса загрузки
- // Полный размер файла - event.total, загружено - event.loaded
- http_request.upload.addEventListener('progress', function(event) {
- var percent = Math.ceil(event.loaded / event.total * 100);
- var back=Math.ceil((100-percent)*6);
- new_div.style.backgroundPosition='-'+back+'px 0px';
- new_div.innerHTML=(name + ': ' + percent + '%');
- }, false);
- // Отправить файл на загрузку
- http_request.open('POST', 'upload.php?fname='+name,true);
- http_request.setRequestHeader("Referer", location.href);
- http_request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
- http_request.setRequestHeader("X-File-Name", encodeURIComponent(name));
- http_request.setRequestHeader("Content-Type", "application/octet-stream");
- http_request.onreadystatechange=ajax_callback(http_request,new_div,name);
- http_request.send(file);
- }
Code (JavaScript) : Убрать нумерацию
- // Callback-фунция для отработки AJAX
- function ajax_callback(http_request, obj, name) {
- return function() {
- if (http_request.readyState == 4) {
- if (http_request.status==200) {
- // Вернулся javascript
- if (http_request.getResponseHeader("Content-Type")
- .indexOf("application/x-javascript")>=0) {
- eval(http_request.responseText);
- }
- // Файл загружен успешно
- else {
- obj.style.backgroundPosition='0px 0px';
- obj.innerHTML=(name + ': 100%');
- }
- }
- else {
- // Ошибка загрузки файла
- }
- }
- }
- }
На этом с загрузкой файлов все. Готовый пример такого загрузчика файлов вы можете посмотреть на демонстрационной странице. Загруженные файлы, по понятной причине, никуда не сохраняются. Ограничение размера загружаемого файла - 15 мегабайт.
Просмотров: 25784 | Комментариев: 17
![](/images/dot.gif)
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Александр
(07.12.2018 в 16:08):
Спасибо! Отлично изложено! По вашему примеру сделал загрузчик на работе, всё пашет как часы! Правда ванильный ajax заменил на axios и логика посерьёзнее, но за основу ваш пример. Ещё раз спасибо что не поленились опубликовать!
![](/images/dot.gif)
ManHunter
(23.02.2016 в 20:57):
А кроссбраузерность? multiple только для очень современных браузеров:
http://caniuse.com/#feat=input-file-multiple
http://caniuse.com/#feat=input-file-multiple
![](/images/dot.gif)
DiPrm
(23.02.2016 в 17:03):
Аналогично раньше думал, что только с помошью flash, но, как оказалось, HTML5 дает такие возможности, добавляя атрибут multiple в поле для загрузки файлов input, что позволяет выбирать несколько файлов и сохранять их в виде массива
В итоге получился такой рабочий пример, как можно адаптировать:
<input type="file" multiple="multiple" onchange="uploadIt(this)">
function uploads (th) {
var file = th.files;
for (i=0; i<file.length; i++){
if (file[i]) {
ajax_upload(file[i]);
}
}
return false;
}
В итоге получился такой рабочий пример, как можно адаптировать:
<input type="file" multiple="multiple" onchange="uploadIt(this)">
function uploads (th) {
var file = th.files;
for (i=0; i<file.length; i++){
if (file[i]) {
ajax_upload(file[i]);
}
}
return false;
}
![](/images/dot.gif)
ManHunter
(20.02.2016 в 16:00):
Это делается через flash или java. Обычными средствами браузера множественный выбор файлов невозможен, так что адаптировать тут нечего.
![](/images/dot.gif)
DiPrm
(20.02.2016 в 15:16):
Спасибо за статью! Интересно было бы почитать про мультизагрузчик через стандартное поле выбора файлов, который также часто встречается последнее время. На сколько сложно адаптировать данный пример под эту задачу?
![](/images/dot.gif)
ManHunter
(18.12.2015 в 19:09):
Ты забыл добавить ".. да побыстрее!!!"
Сперва тон смени, чепушила, потом попробуй попросить еще раз.
Сперва тон смени, чепушила, потом попробуй попросить еще раз.
![](/images/dot.gif)
incognitozz
(18.12.2015 в 18:20):
Ты полный исходник с PHP выложи. Написал статью, приведи пример в исходниках, чтобы не только профи знали как это все делается, но и делетанты...
![](/images/dot.gif)
ManHunter
(11.12.2014 в 17:29):
Чтобы сервер знал, какое имя файла ему передается. На PHP, например, он будет доступен в переменной $_REQUEST['HTTP_X_FILE_NAME']. Это самодельный заголовок, вполне можно обойтись и без него. В примере имя файла дублируется через GET.
![](/images/dot.gif)
Eblinkoff
(11.12.2014 в 17:22):
А вот ещё, скажите пожалуйста, что это за заголовок X-File-Name и зачем он?
![](/images/dot.gif)
ManHunter
(09.12.2014 в 15:55):
Именно так, без JS работать не будет. Браузер или тут же отдаст файл на "скачивание" обратно, или откроет как текстовый/html документ, если формат позволяет.
![](/images/dot.gif)
Eblinkoff
(09.12.2014 в 15:54):
Да, она, проклятая. То есть получается кроссбраузерно, только должен быть включён js... Здорово, спасибо Вам за доступный для понимания пример
![](/images/dot.gif)
ManHunter
(08.12.2014 в 22:15):
Статью целиком прочитать гордость не позволяет?
![](/images/dot.gif)
Eblinkoff
(08.12.2014 в 20:43):
Хотелось бы узнать с какими браузерами совместим этот код...
![](/images/dot.gif)
ManHunter
(23.09.2013 в 13:54):
Ассемблер для души, JS / PHP / SQL для хлеба насущного.
![](/images/dot.gif)
Андрей
(23.09.2013 в 13:49):
Занятно наблюдать, как у одного человека мирно уживаются JavaScript и "Образ мышления: Assembler".
Невольно AJAX (по высокоуровневости и по "// Internet Explorer" ) ассоциировался с Вавилонской башней.
Невольно AJAX (по высокоуровневости и по "// Internet Explorer" ) ассоциировался с Вавилонской башней.
![](/images/dot.gif)
ManHunter
(23.09.2013 в 10:44):
Не уловил шутку юмора про Вавилон.
![](/images/dot.gif)
Андрей
(23.09.2013 в 10:21):
При подобных способах загрузки, как у юзера, у меня всегда возникает вопрос: как будет осуществлена загрузка, параллельно или поочерёдно.
По логике параллельная загрузка может сократить время загрузки (предположительно upload канал будет использован по максимуму). С другой стороны смущает, что при дропе 1000 файлов, "пока они все не загрузятся" результата загрузки видно не будет.
Почему именно параллельная загрузка 6 файлов мне непонятно.
Спасибо за статью. Статья интересная. Хоть и Вавилон, но написано ясно,как-что происходит в клиентской части разобраться можно.
По логике параллельная загрузка может сократить время загрузки (предположительно upload канал будет использован по максимуму). С другой стороны смущает, что при дропе 1000 файлов, "пока они все не загрузятся" результата загрузки видно не будет.
Почему именно параллельная загрузка 6 файлов мне непонятно.
Спасибо за статью. Статья интересная. Хоть и Вавилон, но написано ясно,как-что происходит в клиентской части разобраться можно.
![](/images/dot.gif)
Добавить комментарий
Заполните форму для добавления комментария
![](/images/dot.gif)