
Загрузка файлов перетаскиванием в окно браузера

Загрузка файлов перетаскиванием в окно браузера
Практически все современные 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 мегабайт.
Просмотров: 24363 | Комментариев: 17

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Александр
(07.12.2018 в 16:08):
Спасибо! Отлично изложено! По вашему примеру сделал загрузчик на работе, всё пашет как часы! Правда ванильный ajax заменил на axios и логика посерьёзнее, но за основу ваш пример. Ещё раз спасибо что не поленились опубликовать!

ManHunter
(23.02.2016 в 20:57):
А кроссбраузерность? multiple только для очень современных браузеров:
http://caniuse.com/#feat=input-file-multiple
http://caniuse.com/#feat=input-file-multiple

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;
}

ManHunter
(20.02.2016 в 16:00):
Это делается через flash или java. Обычными средствами браузера множественный выбор файлов невозможен, так что адаптировать тут нечего.

DiPrm
(20.02.2016 в 15:16):
Спасибо за статью! Интересно было бы почитать про мультизагрузчик через стандартное поле выбора файлов, который также часто встречается последнее время. На сколько сложно адаптировать данный пример под эту задачу?

ManHunter
(18.12.2015 в 19:09):
Ты забыл добавить ".. да побыстрее!!!"
Сперва тон смени, чепушила, потом попробуй попросить еще раз.
Сперва тон смени, чепушила, потом попробуй попросить еще раз.

incognitozz
(18.12.2015 в 18:20):
Ты полный исходник с PHP выложи. Написал статью, приведи пример в исходниках, чтобы не только профи знали как это все делается, но и делетанты...

ManHunter
(11.12.2014 в 17:29):
Чтобы сервер знал, какое имя файла ему передается. На PHP, например, он будет доступен в переменной $_REQUEST['HTTP_X_FILE_NAME']. Это самодельный заголовок, вполне можно обойтись и без него. В примере имя файла дублируется через GET.

Eblinkoff
(11.12.2014 в 17:22):
А вот ещё, скажите пожалуйста, что это за заголовок X-File-Name и зачем он?

ManHunter
(09.12.2014 в 15:55):
Именно так, без JS работать не будет. Браузер или тут же отдаст файл на "скачивание" обратно, или откроет как текстовый/html документ, если формат позволяет.

Eblinkoff
(09.12.2014 в 15:54):
Да, она, проклятая. То есть получается кроссбраузерно, только должен быть включён js... Здорово, спасибо Вам за доступный для понимания пример

ManHunter
(08.12.2014 в 22:15):
Статью целиком прочитать гордость не позволяет?

Eblinkoff
(08.12.2014 в 20:43):
Хотелось бы узнать с какими браузерами совместим этот код...

ManHunter
(23.09.2013 в 13:54):
Ассемблер для души, JS / PHP / SQL для хлеба насущного.

Андрей
(23.09.2013 в 13:49):
Занятно наблюдать, как у одного человека мирно уживаются JavaScript и "Образ мышления: Assembler".
Невольно AJAX (по высокоуровневости и по "// Internet Explorer" ) ассоциировался с Вавилонской башней.
Невольно AJAX (по высокоуровневости и по "// Internet Explorer" ) ассоциировался с Вавилонской башней.

ManHunter
(23.09.2013 в 10:44):
Не уловил шутку юмора про Вавилон.

Андрей
(23.09.2013 в 10:21):
При подобных способах загрузки, как у юзера, у меня всегда возникает вопрос: как будет осуществлена загрузка, параллельно или поочерёдно.
По логике параллельная загрузка может сократить время загрузки (предположительно upload канал будет использован по максимуму). С другой стороны смущает, что при дропе 1000 файлов, "пока они все не загрузятся" результата загрузки видно не будет.
Почему именно параллельная загрузка 6 файлов мне непонятно.
Спасибо за статью. Статья интересная. Хоть и Вавилон, но написано ясно,как-что происходит в клиентской части разобраться можно.
По логике параллельная загрузка может сократить время загрузки (предположительно upload канал будет использован по максимуму). С другой стороны смущает, что при дропе 1000 файлов, "пока они все не загрузятся" результата загрузки видно не будет.
Почему именно параллельная загрузка 6 файлов мне непонятно.
Спасибо за статью. Статья интересная. Хоть и Вавилон, но написано ясно,как-что происходит в клиентской части разобраться можно.

Добавить комментарий
Заполните форму для добавления комментария
