Я понял (при взгляде себя), что Есть много демо и учебники, которые показывают вам, как перетащить и падение файла в браузере, а затем сделать его на странице. Они часто помечены как "перетащить-и-падение и загрузить", но они на самом деле не загружать. Этот учебник будет принимать вас, что последний шаг.
Я провещаю вас по примеру, с помощью которого вы можете играть: перетащите файл на веб-страницу, и он будет немедленно загружен на сервер.
Задачи #
Давайте разобить этот процесс на конкретные задачи:
- Захват события падения и считывания его данных.
- Опубликовать эти двоичные данные на сервер.
- Предоставьте обратную связь о ходе загрузки.
- Дополнительно отрисуйте предварительный просмотр загруженного и его статуса.
Для достижения всего этого нам нужны следующие API HTML5 и API, не являющихся HTML5:
Имейте в виду, что не все браузеры поддерживают все эти технологии сегодня, но они становятся все ближе. Я просто хотел создать четкий и полный учебник о том, как идти весь свиней и загрузить, что упал файл.
Конечный результат: мы можем бросить файл в любом месте в браузере, мы получаем предварительный просмотр и прогресс загрузки, и это пятно опыт.

Перетащите и уронит #
Так же, как предупреждены, перетащить и падение, как известно, немного killjoy. На самом деле, это кошмар, но я не буду повторять то, что было сказано до этого.
Наш пример позволит вам перетащить и бросить файл в любом месте браузера. Для этого нам необходимо прикрепить наших слушателей событий к
тел
у ил
и documentEleme
nt (т.е. корневой HTML узел). Слушая документЭлеме
нт, этот код мо
жет быть где угодно на странице, так как documen
tElement всегда
будет существовать. Вы можете слушать на тел
е то
лько один р
аз<bod
y>элемент был столкнулся.</body>
Вот шаблон кода, который нам нужен для захвата события падения на весь документ:
var doc - document.documentElement; doc.ondragover - функция () - this.className - "hover"; возвращение ложное; doc.ondragend - функция () - this.className и ''; returnfalse; doc.ondrop - функция (событие) - event.preventDefault - event.preventDefault(); this.classИмя и ''; теперь сделай что-то с: var файлы и event.dataTransfer.files; возвращение ложным; };
Я использую кл
асс на
ведении, чтобы я мог переключить отзыв, объясняющий пользователю, что файл может быть удален на странице.
Внутри событ
ия па
дения мы можем получить доступ к отброшеным файлам
viaevent.dataTransfer.file
s.
Альтернатива перетаскивания и падения #
Досадно, как я пишу это, я понимаю, это сочетание требований API в настоящее время только удовлетворены Chrome и Firefox. Таким образом, принимая тест от Modernizr, мы можем проверить на поддержку и предоставить нашу альтернативу:
var dndSupported функция () - var div - document.createElement ('div'); возвращение ('draggable' в div) || ('ondragstart' в div 'ondrop' в div); }; если (!dndSupported())
Вместо перетаскивания, мы можем вставить элемент ввода файла (я дал ему идентифик
ат
ор "загрузить"), и когда его значение изменено, файл может быть зачерпнул в:
document.getElementById ('upload').onchange - функция (событие) // "это" относится к элементу события, выпущенного по файлам var - this.files;
Вы можете видеть эквивалент просто фа
йлы с
обственности о
бъектаHTMLInput
Element. Это даст нам доступ к тому же файлу, что и ev
ent.dataTransfer.files
из события падения.
Автоматическое загрузка файла #
Это аккуратный бит, и это болезненно просто. Мы используем функцию спецификации XHR2
: FormDat
a. Как только мы создадим экземпляр F
ormData,
мы можем придать к нему элементы:
var formData - новые формданные (); для (var i й 0; i < files.length; i++) { formData.append('file', f[i]iles); } // now post a new XHR request var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload'); xhr.onload = function () { if (xhr.status === 200) { console.log('all done: ' + xhr.status); } else { console.log('Something went terribly wrong...'); } }; xhr.send (формаДанные);
FormData
Да, вот и все.†
Давайте посмотрим на несколько ключевых вещей, которые происходит на выше код.
formData.append ('файл', файл[i]ы);
Мы отправляем именованные параметры на наш сервер, в частности массив значений, называемых ф
айло
м. Очевидно, что вы можете назвать это как хотите,
но ф
айл имя вашего сервера будет искать, когда он сохраняет загруженный файл (или файлы).
xhr.onload - функция () - если (xhr.status - 200) - консоль.log (все сделано: ' xhr.status); - еще консоль.log ('Что-то пошло ужасно неправильно...'); } };
Если вы знакомы с XHR, вы заметите, что мы не слушаем toon
readystatechange,
тольк
о onl
oad — который (по сути) функция удобства, чтобы вы знали, когда re
adyState
4 (т.е., загружен!). Вы все равно должны проверить и соответствующим образом ответить на код статуса запроса, чтобы убедиться, что это 200 OK, а не 500 (внутренняя ошибка сервера) или 404 (не найдено) или что-нибудь еще.
xhr.send (формаДанные);
Хороший трюк здесь заключается в том, что XHR автоматически установил кодирование размещенных данных на
многочастие/форм-данны
е. Это кодирование позволяет серверу читать и сохранить файлы. Это как кодирование, используемое при отправке вложения по электронной почте.
Предоставление обратной связи пользователю #
XHR2 теперь (flippin', наконец, поставляется с п
рогрессом
события. Так что если вы отправляете или получаете большой файл через XHR, вы можете сказать пользователю, как далеко вы находитесь.
Это довольно просто. Если вы хотите отслеживать ход запроса XHR, прослушайте собы
тие про
гресса. Один gotcha, что поймал меня в течение некоторого времени: Мне нужно отслеживать ход загрузки, а не скачать. Чтобы сделать это правильно, вам нужно прослушать прогресс на объекте загрузкиXHR, как так:
xhr.upload.onprogress - функция (событие) - если (event.lengthComputable) - var complete (event.loaded / event.total - 100 | 0); progress.value - progress.innerHTML - полный; } }; xhr.onload - функция () // на случай, если мы застрям на 99% progress.value и progress.innerHTML No 100;
ем прогрес
са XHR2Обратите внимание, что
вместо xhr.onpro
gress, мы
usexhr.upload.onproges
s. Когда это событие заготовлено, мы проверяем, поддерживает ли событие расчет объема загруженных данных
(thelengthComput
able части), а затем вычисляем сумму завершенной.
В моем HTML я использую эл
емент (по а
налогии с элементом, но бо
лее сема
нтически подходящий, поскольку мы представляем ход задачи), чтобы <progress><meter> показать пользователю, сколько его файла было загружено:</meter> </progress>
<progress id="progress" min="0" max="100" value="0">0</progress>
Обратите внимание, что я исп
ользую innerH
TML для браузеров, которые еще не поддерживают<progr
ess>.</progres
s> Тогда с тире CSS-генерируемого контента, как the
innerHTML
и зн
ачен
ие прогресса может быть одинаковым (возможно, более оптимизации, но я был довольно горд собой в то время!).
И, наконец, рендеринг предварительного просмотра #
В качестве приятного дополнения, мы дадим пользователю предварительный просмотр того, что мы загружаем для них. Для этого требуется API файла, в частности
APIFileRe
ader.
Поскольку операция перетаскивания (ил
и вво[type=file]
д) содержит объект файла, мы можем передать это Файл
Читатель,
чтобы получить содержимое файла. Если это что-то вроде изображения, мы можем получить данные Base64 и дать пользователю предварительный просмотр. Или, если это текст, мы могли бы сделать его в<div
>.</di
v> Тип MIME для файла доступен в качестве с
войс
тва типа на объекте файла.
Итак, давайте предположим, что мы принимаем только изображения. Вот часть предварительного просмотра, которая выполняется после того, как файл был получен браузером:
var acceptedTypes - "изображение/пнг": правда, 'изображение/jpeg': верно, 'изображение/gif': верно; если (принято[file.type]Types - правда) - var reader - новый FileReader (); reader.onload - функция (событие) - var изображение - новое изображение (); image.src и event.target.result; image.width No 100; поддельные мизе document.body.appendChild (изображение); }; reader.readAsDataURL (файл); }
Мы создаем Fi
leReader
и даем ему файл для чтения. В приведеном выше примере я использовал
readAsDataURL, н
о вы также можете читать файлы в простом тексте и двоичных форматах (в соответствии с спецификацией).
Когда читатель прочитал файл и данные доступны, он запускает событие загрузки, ко
торо
е, в свою очередь, создает наше новое изображение.
Результат действия чтения файла находится в
event.target.result
property. В случае readAsDat
aURL, значен
ие находится вдоль линий данных:и
зображение/png;base64,ABC...
.
Использование всех инструментов в сарае #
Этот пример может быть немного надуманным для статьи, которую я хотел написать. Я использовал много различных технологий, чтобы сделать что-то, что является довольно распространенной моделью в Интернете. В самом деле, это потому, что у меня были проблемы с поиском окончательного источника на загрузку на фактический сервер (за исключением, конечно, как я написал эту статью я нашел этот пример еще в конце 2010 года!).
Многообещающе, вы увидите как каждый бит техника может работать совместно для того чтобы создать применение, но поровну я надеюсь что вы может увидеть где это работало бы если никакие или как раз некоторые из технологии не были имеющиеся. Убедитесь, что вы обнаруживаете функциональность. Убедитесь, что вы предоставляете обратные варианты. Убедитесь, что вы развиваете ответственно.
Вот окончательный перетащить-и-падение и загрузить демо для вас, чтобы играть.