Скрипт для выбора файла
Это работает в Windows XP и выше и обеспечивает выбор единственного файла (без множественного выбора файлов). Это диалоговое окно открытия файла фактически используется в апплете панели управления "Учетные записи пользователей" (C:\WINDOWS\system32\nusrmgr.cpl). Вы можете задать фильтры по расширениям файлов (свойство Filter), выбрать фильтр по умолчанию (свойство FilterIndex), задать начальный каталог (свойство InitialDir).
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.
Прячем input
Теперь нам нужно спрятать input[type=file] . Первое, что бросается в голову — свойства display: none и visibility: hidden . Но тут не все так просто. На некоторых старых браузерах клик по метке перестанет производить какой-либо эффект. Но это не все. Как известно, невидимые элементы не могут получать фокус, а кто бы что ни говорил, фокус важен, так как для некоторых людей это единственная возможность взаимодействия с сайтом. Так что этот способ нас не устраивает. Пойдем обходным путем:
Абсолютно спозиционируем наш input[type=file] относительно его родительского блока, уменьшим до 0.1px , сделаем прозрачным и установим его z-index меньше, чем у родителя, чтоб, так сказать, наверняка.
Поздравляю, мы добились того, чего хотели: наше поле выглядит именно так, как на предыдущей картинке.
Настраиваем фокус
Так как наш input[type=file] физически присутствует на страницу, он имеет возможность получать фокус. То есть, если мы будем нажимать на странице клавишу Tab , то в какой-то момент фокус перейдет на input[type=file] . Но проблема в том, что мы этого не увидим: выделяться будет поле, которое мы скрыли. Да, если в этот момент мы нажмем Enter , то диалоговое окно откроется и все будет работать как надо, вот только как мы поймем, что нажимать уже пора?
Наша задача — определенным образом выделить метку в момент, когда фокус расположен на поле загрузки файлов. Но как нам это сделать, если метка получать фокус не может? Знатоки CSS3 сразу же подумают о псевдоклассе :focus , который определяет стили для элементов в фокусе, и селекторах + или ~ , которые выбирают правых соседей: элементы, расположенные на том же уровне вложенности, идущие после выбранного элемента. Если учесть, что в нашей разметке input[type=file] расположен прямо перед тэгом label , имеет место быть следующая запись:
Но опять же, не все так просто. Для начала давайте обсудим, каким образом нам следует выделить метку. Как известно, все современные и не очень браузеры имеют уникальные свойства по умолчанию для элементов в фокусе. В основном, это свойство outline , которое создает вокруг элемента обводку, отличающуюся от border тем, что не изменяет размер элемента и может быть отодвинута от него. Как правило, люди пользуются только одним браузером, поэтому привыкают именно к его стандартам. Чтобы людям было проще ориентироваться на нашем сайте, мы должны постараться настроить фокус так, чтобы он выглядел максимально естественно для большинства популярных современных браузеров. В теории, с помощью JavaScript можно получить информацию о том, через какой браузер пользователь открыл сайт, и в соответствии с этим настроить стили, но в рамках статьи, предназначенной в первую очередь для новичков, эта тема слишком сложна и громоздка. Постараемся обойтись малой кровью.
В браузерах, основанных на движке WebKet (Google Chrome, Operа, Safari), свойство по умолчанию для элементов в фокусе имеет вид:
Здесь -webkit-focus-ring-color — специфичный только для данного движка цвет фокусной обводки. То есть, эта строчка будет работать исключительно в WebKit-браузерах, а это именно то, что нам нужно. Укажем данное свойство для нашей метки:
Открываем Google Chrome или Opera, смотрим. Все работает как надо:
Посмотрим, как обстоят дела с фокусом в Mozilla Firefox и Microsoft Edge. Для этих браузеров свойство по умолчанию имеет вид:
К сожалению, префикс -moz- со свойством outline работать не будет. Поэтому нам придется выбирать, какое из этих двух свойств мы выберем. Так как количество пользователей Firefox значительно выше, рациональнее отдать предпочтение именно этому браузеру. Это не значит, что мы лишим пользователей Edge и других браузеров возможности видеть, где сейчас фокус, просто он у них будет выглядеть «неродным». Что ж, приходится идти на жертвы.
Добавляем стиль из Mozilla Firefox перед стилем для WebKit: сначала все браузеры применят первое свойство, а затем те, которые могут (Google Chrome, Opera, Safari и др.), применят второе.
И вот тут начинается странное: в Edge все работает нормально, а вот Firefox по каким-то неведомым причинам отказывается применять свойства к метке при фокусе на input[type=file] . Причем само событие focus случается — проверил через JavaScript. Более того, если принудительно установить фокус на поле выбора файла через инструменты разработчика, то свойство применится и наша обводка появится! Видимо, это баг самого браузера, но если у кого-то есть идеи, почему такое происходит — пишите в комментариях.
Ну ничего, нормальные герои всегда идут в обход. Как я сказал ранее, событие focus случается, а значит, регулировать свойства мы можем прямиком из JavaScript. Но для этого нам придется поменять логику нашего селектора:
Опишем класс .focus для нашей метки и будем добавлять его каждый раз, когда input[type=file] получает фокус и убирать, когда теряет.
Теперь все работает как надо. Поздравляю, с фокусом мы разобрались.
Пример: Отображение размера файла(ов)
Следующий пример показывает возможное использование свойства size :
Пример: Использование URL объектов для отображения PDF
URL объектов могут быть использованы не только для изображений! Также этот приём можно использовать и для других ресурсов, которые могут отображаться браузером, например, файлы PDF.
В Firefox, для того чтобы файл PDF появился в iframe и не предлагался для загрузки, нужно установить pdfjs.disabled в значение false Non-Standard .
А здесь изменение атрибута src :
3 Ответ от mozers 2007-11-30 11:02:35 (изменено: mozers, 2007-12-01 00:41:02)
- mozers
- Разработчик
- Неактивен
Еще один вариант (работает под любой виндой):
P.S.При возникновении проблем с лицензированием, ответ подскажет Google
Использование URLs объектов
Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) представляет поддержку для методов DOM window.URL.createObjectURL() (en-US) и window.URL.revokeObjectURL() (en-US). Они позволяют создавать простые строки URL, которые могут быть использованы для обращения к любым данным, на которые можно ссылаться, используя объект DOM File , включая локальные файлы на компьютере пользователя.
Когда у вас есть объект File , на который вы хотите ссылаться по URL из HTML, вы можете создать для этого объект URL, такой как этот:
URL объекта – это строка, идентифицирующая объект файла File . Каждый раз при вызове window.URL.createObjectURL() (en-US), создаётся новый уникальный объект URL, даже если вы уже создали объект URL для этого файла. Каждый из них должен быть освобождён. В то время как они освобождаются автоматически когда документ выгружается, если ваша страница использует их динамически, вы должны освободить их явно вызовом window.URL.revokeObjectURL() (en-US):
Пример: Загрузка файла, выбранного пользователем
Ещё одна вещь, которую вы можете захотеть сделать – это позволить пользователю загрузить выбранный файл или файлы (такие, как изображения из предыдущего примера) на сервер. Это можно сделать асинхронно довольно просто.
4 Ответ от The gray Cardinal 2007-11-30 22:35:50
- The gray Cardinal
- Разработчик
- Неактивен
Можно вызвать диалог выбора файла, используя ActiveX-объект "InternetExplorer.Application": создаём страницу с элементом FileUpload () и вызываем его метод click(), что в случае IE имитирует щелчок по кнопке "Обзор":
Окошко минимизируем, но делаем видимым, т.к. иначе, если будут открыты другие окна IE, диалог будет выводится под ними и о его существовани нельзя будет догадаться; а так он будет либо сам выводится на переднем плане, либо на панели задач будет мигатющая кнопка, позволяющая переключится на него.
Автор примера - wisgest.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.
Пример: Использование URL объектов с другими типами файлов
Вы можете таким же образом работать с файлами в других форматах. Ниже приведён пример как загружается видео:
По итогу хочу сказать
Если этот класс поможет хотя бы одному человеку я буду очень рад этому. Как я уже говорил в начале буду рад конструктивной критике и дополнениям которые могут привести к улучшению класса. Ссылка на CargaDes.class.
Изменил в статье способы использования класса. И добавил описание того что изменилось в классе.
Вот закончил работу над ошибками, если это можно так назвать.
Что было сделано:
Что было не сделано:
- Перевод комментариев на английский(если это все одно никому не надо, то зачем тратить время);
- Не сменил названия функций на более понятные(мне не ясно какие, если английские, то смотреть пункт N1);
- Автотесты смотрел, но это оч. сложно сделать универсально т.к. у каждого свои сценарии действий, хотя может я ошибаюсь, то если вы считаете это нужным в классе который никому не нужен у вас есть возможность мне в этом помочь;
- Возможно еще что-то, но я уже не знаю что и у вас есть такая возможность мне об этом сказать.
Благодарю за конструктивную критику webdevium и alutskevich, если бы мог, то плюсанул бы вам обязательно.
Так же благодарю всех остальных т.к. у меня появилось понимание моей главной ошибки и родилось пару идей.
Все течет, все меняется, но только input[type=file] как портил нервы всем начинающим веб-разработчикам, так и продолжает это делать до сих пор. Вспомните себя N лет назад, когда вы только начинали постигать азы создания веб-сайтов. Молодой и неопытный, вы искренне удивлялись, когда кнопка выбора файла напрочь отказывалась менять цвет своего фона на ваш любимый персиковый. Именно в тот момент вы впервые столкнулись с этим несокрушимым айсбергом под названием «Загрузка файлов», который и по сей день продолжает «топить» начинающих веб-разработчиков.
На примере создания поля для загрузки файлов я покажу вам, как правильно прятать input[type=file] , настраивать фокус на объекте, у которого фокуса быть не может, обрабатывать события Drag-and-Drop и отправлять файлы через AJAX. А также я познакомлю вас с парой браузерных багов и путями их обхода. Статья написана для новичков, но в некоторых моментах может быть полезна и занимательна даже для матерых разработчиков.
2 Ответ от The gray Cardinal 2006-07-19 22:51:50
- The gray Cardinal
- Разработчик
- Неактивен
Другой способ выбора файла: библиотека C:\WINDOWS\system32\safrcdlg.dll предоставляет объект "SAFRCFileDlg.FileOpen". Здесь нет практически никаких настроек. Это работает в Windows XP и выше.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.
1. Отдача файла через браузер без показа его места хранения с возможностью докачки и регулирования скорости
Этот метод очень похож на Drupal и иже с ним:
Я добавил еще отдачу с помощью Apache, но должна быть включена директива XSendFile On
Сразу после выполнения метода браузер выдаст окно для сохранения файла
Доступ к выбранным файлам
Рассмотрим следующий код:
File API делает возможным доступ к FileList , который содержит объекты File , которым соответствуют файлы, выбранные пользователем.
Атрибут multiple элемента input позволяет пользователю выбрать несколько файлов.
Обращение к одному выбранному файлу с использованием классической DOM-модели:
Обращение к одному выбранному файлу через jQuery:
Ошибка "files is undefined" означает что был выбран не один HTML-элемент, а список элементов, возвращаемый jQuery. Необходимо уточнить, у какого именно элемента требуется вызвать метод "files"
Преамбула
Из кода для упрощения сознательно выкинуты все процедуры проверки принятого файла и try-catch вызовов функций, так как эти моменты не являются темой данной статьи. Также не охватывается момент по предотвращению звукового сигнала в IE. В работе используем технологию Ajax, подразумевающую, что у нас есть основная страница, осуществляющая взаимодействие с пользователем(front-end) и скрипт на сервере, обрабатывающая наши запросы(back-end)
8 Ответ от wisgest 2020-11-10 03:14:01 (изменено: wisgest, 2020-11-10 03:41:45)
- wisgest
- Разработчик
- Неактивен
Проверил работоcпособность совместно с IE11 моего решения 2007 года: оказалось, каталог в пути к выбранному файлу подменяется на C:\fakepath\ (подобное поведение, по-видимому, имеет место и в немного более ранних выпусках IE).
Но всё работает как надо, если заменить
Также у меня имеются подозрения, что (в зависимости от настроек IE) запрос "http:///" может вызвать то ли открытие сетевого подключения, то ли выход из автономного режима просмотра — что-то подобное я обнаружил около того же 2007 года.
Можно, конечно, явно указать запрос к ресурсам, но если не таскать рядом со сценарием заранее подготовленного файла с ресурсами, то его может не оказаться (например, с IE6 нет ieframe.dll).
А что, если попробовать
(Предполагаю, что поколдовав с настройками безопасности, можно всё-таки заставить работать с последними выпусками IE и "about:blank" и, наоборот, испортить "res://"…)
Предлагаю на суд сообщества свой велосипед. На написание данного текста вдохновил Способ №5 из материала Делаем красивый input[type=file] для адаптивного сайта… И да — все работает в IE, начиная с 9 версии.
Цель: создать свою кнопку/элемент управления по нажатию которой происходит загрузка файла на сервер (либо иные, предусмотренные разработчиком, файловые операции).
Инструменты: CSS, PHP, JavaScript.
Используемые технологии: Ajax, через скрытый iframe.
Использование метода click() скрытых элементов выбора файла
Рассмотрим следующую разметку HTML:
Код, обрабатывающий событие click, может выглядеть следующим образом:
Таким образом, вы можете стилизовать новую кнопку открытия диалога выбора файла так, как пожелаете.
Разметка и первичные стили
Начнем с HTML-разметки:
Пожалуй, главным элементом, на который стоит обратить внимание, является
Спецификация HTML не позволяет нам накладывать визуальные свойства непосредственно на input[type=file] , но мы имеем тэг label , нажатие на который вызывает клик по элементу формы, к которому он привязан. К нашей радости, данный тэг никаких ограничений в стилизации не имеет: мы можем делать с ним все, что захотим.
Вырисовывается план действий: стилизуем метку как нам угодно, а сам input[type=file] прячем с глаз долой. Для начала настроим общие стили страницы:
Теперь стилизуем нашу метку:
То, к чему мы стремимся ( input[type=file] убран из разметки):
Безусловно, можно было отцентровать метку, добавить фон и границу, получив полноценную кнопку, но наш приоритет — Drag-and-Drop.
4. Отдаем файл на удаленный сервер со своего сервера
Использование элемента label скрытого элемента input
Для того, чтобы открыть диалог выбора файла без использования JavaScript (метода click()), можно воспользоваться элементом .
Рассмотрим следующую разметку HTML:
В данном случае нет необходимости добавлять код JavaScript для того, чтобы вызвать fileElem.click() . Также в данном случае вы можете стилизовать элемент label так, как пожелаете.
Асинхронная обработка процесса загрузки
Создание заданий на загрузку
Продолжая пример с кодом, который строил эскизы в предыдущем примере, напомним, что каждому изображению эскиза присвоен класс CSS class obj , с соответствующим File , прикреплённым в атрибут file . Это позволяет нам очень просто выбрать все изображения, которые пользователь выбрал для загрузки используя Document.querySelectorAll() , как показано здесь:
Строка 2 получает NodeList в переменную imgs со всеми элементами документа, имеющих класс CSS obj . В нашем случае все они будут эскизами изображений. Как только мы получим этот список, можно просто пройти по нему, создавая для каждого элемента новый экземпляр FileUpload . Каждый из них отвечает за загрузку соответствующего файла.
Пример: Использование URL объектов для отображения изображений
Этот пример использует URL объектов для отображения эскизов изображений. Кроме этого, оно показывает другую информацию о файлах, включая их имена и размеры. Вы можете посмотреть работающий пример.
HTML, который представляет интерфейс, выглядит так:
Метод handleFiles() может быть реализован таким образом:
Если объект FileList , передаваемый в handleFiles() является null , то мы просто устанавливаем внутренний HTML блока в отображение текста "No files selected!". Иначе мы начинаем строить список файлов таким образом:
- Создаётся новый элемент - неупорядоченный список ( ).
- Этот новый элемент вставляется в блок с помощью вызова его метода element.appendChild() .
- Для каждого File в FileList , представляемого files :
- Создаём новый элемент пункта списка ( ) и вставляем его в список.
- Создаём новый элемент изображения ( ).
- Устанавливаем источник изображения в новый URL объекта, представляющий файл, используя window.URL.createObjectURL() (en-US) для создания URL на двоичный объект.
- Устанавливаем высоту изображения в 60 пикселей.
- Устанавливаем обработчик события загрузки изображения для освобождения URL объекта, т.к. после загрузки изображения он больше не нужен. Это делается вызовом метода window.URL.revokeObjectURL() (en-US), передавая в него строку URL объекта, которая указана в img.src .
- Добавляем новый элемент в список.
Доступ к выбранным файлам через событие change
Также возможно (но не обязательно) получить доступ к FileList через событие change . Нужно использовать EventTarget.addEventListener() чтобы добавить обработчик события change , как показано здесь:
Обработчик события change можно назначить атрибутом элемента:
Когда пользователь выбирает файл, функция handleFiles() будет вызвана с объектом FileList , который состоит из объектов File , представляющих файлы, выбранные пользователем.
2. Загрузка файла/ов на сервер через браузер с индикатором прогресса
После выполнения метода появится кнопка для выбора файлов и кнопка для загрузки файлов. Индикатор будет появляться для каждого выбранного файла в отдельности.
Управление процессом загрузки файла
Функция FileUpload принимает на вход 2 параметра: элемент изображения и файл, из которого нужно читать данные изображения.
Перед началом загрузки данных выполняются несколько шагов для подготовки:
Выбор файлов с использованием технологии drag and drop
Также вы можете предоставить пользователю возможность непосредственно перетаскивать файлы в ваше веб-приложение.
На первом шаге необходимо определить зону, в которую будут перетаскиваться файлы. В каждом конкретном случае часть содержимого вашей страницы, ответственная за приёмку перетаскиваемых файлов, может варьироваться в зависимости от дизайна приложения, тем не менее, заставить элемент воспринимать события перетаскивания достаточно просто:
В данном примере мы превращаем элемент с ID, равным dropbox, в нашу зону перетаскивания при помощи добавления обработчиков для событий dragenter , dragover и drop .
В нашем случае нет необходимости делать что-то особенное при обработке событий dragenter и dragover , таким образом, обе функции, ответственные за обработку данных событий, довольно просты. Они останавливают распространение события и предотвращают возникновение действия по умолчанию:
Вся настоящая магия происходит в функции drop() :
Здесь мы извлекаем из события поле dataTransfer , затем вытаскиваем из него список файлов и передаём этот список в handleFiles() . После этого процесс обработки файлов одинаков вне зависимости от того, использовал ли пользователь для их выбора элемент input или технологию drag and drop.
3. Скачивание файлов с удаленного сервера на свой сервер
2 Ответ от The gray Cardinal 2006-07-19 22:51:50
- The gray Cardinal
- Разработчик
- Неактивен
Другой способ выбора файла: библиотека C:\WINDOWS\system32\safrcdlg.dll предоставляет объект "SAFRCFileDlg.FileOpen". Здесь нет практически никаких настроек. Это работает в Windows XP и выше.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.7 Ответ от The gray Cardinal 2009-02-28 14:52:10
- The gray Cardinal
- Разработчик
- Неактивен
Бесплатный COM-сервер JSSys3.dll предоставляет методы для вывода окон выбора файлов (в т.ч. нескольких), для сохранения файла, для вывода окон выбора цвета, выбора папки. Пример:
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.6 Ответ от The gray Cardinal 2009-02-28 13:25:51
- The gray Cardinal
- Разработчик
- Неактивен
Бесплатный COM-сервер JSDlgBox.dll предоставляет упрощённые методы для вывода окон выбора и сохранения файлов, а также окон выбора цвета. Методы не имеют никаких параметров. Дистрибутив (архив) компонента имеет размер чуть более 10 Кб. Пример:
Похожие методы предоставляет бесплатный компонент JSForm.dll.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.Технология работы
1. На главной странице создаем «form action» Делаем ей target на скрытый фрейм, который создаем статически (или динамически). Создаем два «input» с типом «file» и «submit», даем им «id», помещаем их в «div», который спрячем со страницы стилем. Все эти элементы не видимы для пользователя и не воспринимают каких-либо его действий.
2. Начинаем «магию». Для «input» с типом «file» на событие по изменению вешаем вызов функции onchange=«LoadFile();».
3. На главной странице создаем кнопку. Навешиваем ей на событие нажатия кнопки мыши вызов функции onclick=«FindFile();».
4. В функции FindFile() имитируем клик на «input» с типом «file». То есть при нажатии на нашу кнопку вызывается стандартный диалог выбора файла. Как только пользователь выбрал файл, срабатывает событие onchange и вызывается функция LoadFile(). В функции LoadFile() имитируем клик на «input» с типом «submit».
5. Форма формирует POST запрос с именем файла к нашему back-end скрипту, который осуществляет все проверки по безопасности и загрузку файла. После этого скрипт вызывает callback функцию главной страницы, которой сообщает о результате выполнения.Собственно все. Для примера приведены четыре основных файла, код которых приведён ниже:
css/style.css – стили главной страницы
view/upload.php – back-end скрипт загрузки файла
index.php – главная страницы
js/upload.js – front-end скрипты главной страницыКроме того, необходим любой файл с картинкой для кнопки buttons/openfile.jpg
Раньше я об этом не задумывался и пользовался готовым решением типа от Drupal для отдачи файлов и более мне не надо было. Пока несколько месяцев назад у меня не возникла острая необходимость не только отдавать файлы.В интернете есть много информации о том как скачивать файлы с сервера и загружать файлы на сервер, а также между серверами. Но нигде нет простого решения которое было бы более ли менее универсально.
Я несколько дней убил на изучение всяких заголовков и вариаций использования cUrl, но собрать все воедино не выходило. Видел много разных подобных классов, но везде было либо частичное решение, либо очень запутанно, либо и то, и другое.
И лишь благодаря единичным статьям, кусочкам информации с форумов и всяким комментариям удалось собрать пазл воедино. Я не утверждаю что мое решение полностью универсально, но очень удобное во многих случаях, хотя это вам решать.
Если у кого-либо возникнет желание улучшить мое решение этого вопроса и хватает знаний в этом направлении, то я буду рад, если вы сделаете какие-либо исправления или добавления к коду который лежит в открытом доступе на GitHub.
А теперь к делу, функции класса CargaDes:
- Отдача файла через браузер без показа его места хранения и с возможностью докачки;
- Загрузка файла на сервер через браузер с индикатором прогресса;
- Скачивание файлов с удаленного сервера на свой сервер с индикатором прогресса;
- Загрузка файлов со своего сервера на удаленный сервер с индикатором прогресса.
Для начала нужно скачать и подключить класс CargaDes:
Drag-and-Drop
Работа с Drag-and-Drop осуществляется путем отслеживания специальных браузерных событий: drag, dragstart, dragend, dragover, dragenter, dragleave, drop . Подробное описание каждого из них вы с легкостью сможете найти в интернете. Мы будем отслеживать только некоторые из них.
Для начала определим Drag-and-Drop-элемент:
Затем опишем в CSS специальный класс, который будем присваивать dropZone , когда курсор, тянущий файл, будет прямо над ним. Это нужно, чтобы визуально проинформировать пользователя о том, что файл уже можно отпустить.
Теперь перейдем в JS-файл. Для начала, нам необходимо отменить все действия по умолчанию на события Drag-and-Drop. Например, одно из таких событий — открытие кинутого файла браузером. Нам это совершенно не нужно, поэтому пропишем следующие строчки:
В jQuery вызов оператора return false эквивалентен вызову сразу двух функций: e.preventDefault() и e.stopPropagation() .Начнем описывать свой собственный обработчик событий. Поступим так же, как делали с фокусом, но на этот раз будем отслеживать события dragenter и dragover для добавления класса и событие dragleave для его удаления:
А происходит это мерцание из-за того, что при наведении курсора на дочерний элемент dropZone , будь то картинка или div с полем выбора файлов и меткой, по какой то причине срабатывает событие dragleave . Нам очевидно, что поле мы не покидаем, а вот браузерам, почему-то, нет, и из-за этого они без зазрения совести убирают класс .focus у dropZone .
И вновь нам придется как-то выкручиваться. Если браузер сам не понимает, что поле мы не покидаем, придется ему помочь. А делать мы это будем через дополнительные условия: вычислим координаты мыши относительно dropZone , а затем проверим, вышел ли курсор за пределы блока. Если вышел, значит убираем стиль:
И все, проблема решена! Вот так выглядит наше поле с файлом внутри:Переходим к обработке самого события drop . Но для начала вспомним, что, помимо Drag-and-Drop, у нас есть input[type=file] , и каждый из этих способов независим по своей сути, но должен выполнять одинаковые действия: загружать файлы. Поэтому я предлагаю создать отдельную универсальную для обоих методов функцию, в которую мы будем передавать файлы, а она уже будет решать, что с ними сделать. Назовем ее sendFiles() , но опишем чуть позже. Для начала обработаем событие drop :
Сначала уберем класс .dragover у dropZone . Затем получим массив, содержащий файлы. Если вы используете jQuery, то путь будет e.originalEvent.dataTransfer.files , если пишите на чистом JS, то e.dataTransfer.files . Ну а затем передаем массив в нашу пока еще нереализованную функцию.Теперь проработаем способ загрузки через input[type=file] :
Отслеживаем событие change на кнопке выбора файлов, получаем массив через this.files и отправляем его в функцию.Отправка файлов через AJAX
Последний этап — описание функции обработки файлов — уникален для всех и каждого. Он будет прямым образом зависеть от той цели, которую вы преследуете. Для примера я покажу, как отправлять файлы на сервер через AJAX.
В переменную maxFileSize занесем максимальный размер файла, который будем отправлять на сервер. Функцией FormData() мы создадим новый объект класса FormData , позволяющий формировать наборы пар ключ-значение. Такой объект можно легко отправлять через AJAX. Далее используем jQuery конструкцию .each для массива files , которая применит заданную нами функцию для каждого его элемента. В качестве аргументов в функцию будут передаваться порядковый номер элемента и сам элемент, которые мы будем обрабатывать как index и file соответственно. В самой функции мы проверим файл на соответствие нашим критериям: размер меньше пяти мегабайт, а тип — PNG или JPEG. Если файл проходит проверку, то добавляем его в наш объект FormData путем вызова функции append() . Ключом послужит строка 'photos[]' , квадратные скобки на конце которой обозначат, что это массив, в котором может быть несколько объектов. Самим объектом будет file .Теперь все готово для отправки файлов через AJAX. Добавим в нашу функцию следующие строчки:
Поздравляю, теперь вы умеете создавать свое собственное поле загрузки файлов! Конечно же, я не позиционирую свой способ как единственно верный и правильный. Своей задачей я ставил показать общий ход решения данной задачи, подходящий в первую очередь для новичков. Если вы считаете, что где-то что-то можно было сделать лучше — пишите в комментариях, обсудим!
Используя File API, добавленный к DOM в HTML5, в веб-приложениях теперь можно запрашивать пользователя выбрать локальные файлы и затем читать содержимое этих файлов. Выбор файлов может осуществляться с помощью элемента или drag and drop.
Если вы хотите использовать DOM File API в расширениях или коде Chrome, используйте. На самом деле, в таком случае вам необходимо ознакомиться с дополнительными нюансами. См. статью Using the DOM File API in chrome code для подробностей.
Получение информации о выделенных файлах
Объект FileList предоставляемый классическим DOM содержит все файлы выбранные пользователем, каждый из которых представляет собой объект File . Вы можете определить сколько файлов выбрал пользователь проверяя значение атрибута длины ( length ) списка файлов:
Конкретные объекты File могут быть получены обращением к списку файлов как к массиву:
Этот цикл проходит по всем файлам в списке файлов.
Всего существует три атрибута, предоставляемых объектом File , которые содержат полезную информацию о файле.
name Имя файла как строка доступная только для чтения. Это просто имя файла и оно не включает в себя информацию о пути. size Размер файла в байтах, как 64-битное целое число (возможно только чтение). type MIME тип файла, как строка доступная только для чтения, или пустая строка ( "") если тип файла не может быть определён.
Пример: Отображение эскизов изображений, выбранных пользователем
Представим, что вы разрабатываете очередной веб-сайт для обмена фотографиями и вы хотите использовать возможности HTML5 для предварительного просмотра изображений перед тем, как пользователь загрузит их. Вы можете создать input элемент или зону перетаскивания, как обсуждалось ранее, и вызвать такую функцию, как handleFiles() ниже.
Здесь наш цикл обрабатывает выбранные пользователем файлы, проверяя атрибут type у каждого файла, чтобы определить является ли файл изображением (выполняется регулярное выражение в строке " image.* "). Для каждого файла, который является изображением, мы создаём новый img элемент. Можно использовать CSS для установки красивых рамок, теней, и указания размеров изображения, но здесь нет нужды делать этого.
Каждое изображение имеет CSS класс obj добавленный к нему для упрощения его поиска в DOM дереве. Мы также добавили атрибут file к каждому изображению, указав File ; это позволит нам получить изображения для фактической загрузки позже. Наконец, мы используем Node.appendChild() для того, чтобы добавить новый эскиз в область предпросмотра нашего документа.
Затем мы устанавливаем FileReader для обработки асинхронной загрузки изображения и прикрепления его к img элементу. После создания нового объекта FileReader , мы настраиваем его функцию onload , затем вызываем readAsDataURL() для запуска операции чтения в фоновом режиме. Когда всё содержимое файла изображения загружено, они преобразуют его в data: URL, который передаётся в колбэк onload . Наша реализация этой процедуры просто устанавливает атрибут src у элемента img загруженного изображения, в результате чего миниатюра изображения появляется на экране пользователя.
5 Ответ от The gray Cardinal 2007-12-13 22:35:38
- The gray Cardinal
- Разработчик
- Неактивен
Пример опубликовал Large Null.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.Читайте также: