Статьи

Как использовать HTML5 File Drag and Drop

Перетаскивание файлов с рабочего стола в браузер — одна из главных целей интеграции веб-приложений. Это первая из четырех статей, в которой рассказывается, как:

  1. включить перетаскивание файла на элемент веб-страницы
  2. анализировать удаленные файлы в JavaScript
  3. загружать и анализировать файлы на клиенте
  4. асинхронно загружать файлы на сервер, используя XMLHttpRequest2
  5. покажите графический индикатор выполнения во время загрузки
  6. Используйте прогрессивное улучшение, чтобы убедиться, что ваша форма загрузки файлов работает в любом браузере (хорошая новость для всех вас, поклонников IE6!)
  7. закодируйте его на обычном JavaScript без библиотеки.

Уф.

Большой, плохой браузер Поддержка

Прежде чем мы начнем, в этом руководстве рассматриваются несколько передовых технологий HTML5, поэтому ожидайте, что поддержка будет неоднозначной. Код работает сегодня, но, возможно, API изменятся и браузеры будут развиваться.

  • Последние версии Firefox и Chrome поддерживают все функции и работают отлично.
  • Opera может анализировать файлы в JavaScript, но удаление файлов и загрузка XMLHttpRequest2 не реализованы.
  • IE и настольные версии Safari не поддерживают ни один из API.
  • Apple отключила формы загрузки HTML-файлов в версиях Safari для iPhone и iPad. Кто-нибудь знает почему?

Наконец, обратите внимание, что мой код показывает основные понятия. Есть небольшая проверка ошибок, и вам нужно будет адаптировать ее для производственной системы.

HTML и CSS

Вот наша стандартная форма с типом ввода файла. Единственная особенность HTML5 — это атрибут «множественный», который позволяет пользователю выбирать любое количество файлов.

Мы будем загружать файлы на сервер, работающий на PHP, но код будет одинаковым независимо от используемой технологии. Скрытое значение MAX_FILE_SIZE указывает 300 000 байтов — это используется PHP, но мы также проверим его на стороне клиента, чтобы предотвратить загрузку огромных файлов.


<form id="upload" action="upload.php" method="POST" enctype="multipart/form-data">

<fieldset>
<legend>HTML File Upload</legend>

<input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="300000" />

<div>
	<label for="fileselect">Files to upload:</label>
	<input type="file" id="fileselect" name="fileselect[]" multiple="multiple" />
	<div id="filedrag">or drop files here</div>
</div>

<div id="submitbutton">
	<button type="submit">Upload Files</button>
</div>

</fieldset>

</form>

<div id="messages">
<p>Status Messages</p>
</div>

Элемент #filedrag будет использоваться как место для перетаскивания файла. Элемент скрыт в CSS, но он будет включен в JavaScript, если поддерживается перетаскивание:

 
#filedrag
{
	display: none;
	font-weight: bold;
	text-align: center;
	padding: 1em 0;
	margin: 1em 0;
	color: #555;
	border: 2px dashed #555;
	border-radius: 7px;
	cursor: default;
}

#filedrag.hover
{
	color: #f00;
	border-color: #f00;
	border-style: solid;
	box-shadow: inset 0 3px 4px #888;
}

Мы также определили класс .hover, который меняет стиль, когда пользователь перетаскивает файл в элемент. Браузеры не применяют стиль: hover в этой ситуации, но мы можем добавить класс с JavaScript, когда происходит событие.

Файловый API

Файловый API W3C предоставляет несколько объектов. Мы будем использовать:

  • FileList : представляет массив выбранных файлов.
  • Файл : представляет отдельный файл.
  • FileReader : интерфейс, который позволяет нам читать данные файла на клиенте и использовать их в JavaScript.

Присоединение событий JavaScript

Время испачкать руки с помощью JavaScript. Мы не используем библиотеку JavaScript, поэтому, чтобы сохранить отпечатки пальцев, мы создадим несколько вспомогательных функций для возврата элемента по идентификатору и вывода сообщений о состоянии:

 
// getElementById
function $id(id) {
	return document.getElementById(id);
}

//
// output information
function Output(msg) {
	var m = $id("messages");
	m.innerHTML = msg + m.innerHTML;
}

Теперь мы проверим, доступен ли File API, и вызовем функцию Init ():

 
// call initialization file
if (window.File && window.FileList && window.FileReader) {
	Init();
}

//
// initialize
function Init() {

	var fileselect = $id("fileselect"),
		filedrag = $id("filedrag"),
		submitbutton = $id("submitbutton");

	// file select
	fileselect.addEventListener("change", FileSelectHandler, false);

	// is XHR2 available?
	var xhr = new XMLHttpRequest();
	if (xhr.upload) {
	
		// file drop
		filedrag.addEventListener("dragover", FileDragHover, false);
		filedrag.addEventListener("dragleave", FileDragHover, false);
		filedrag.addEventListener("drop", FileSelectHandler, false);
		filedrag.style.display = "block";
		
		// remove submit button
		submitbutton.style.display = "none";
	}

}

Функция Init ():

  1. Устанавливает прослушиватель события «change» для элемента ввода файла.
  2. Отображает элемент #filedrag.
  3. Устанавливает прослушиватели событий «dragover» и «dragleave» для изменения стиля элемента #filedrag.
  4. Устанавливает прослушиватель события drop для элемента #filedrag.
  5. Скрывает кнопку отправки формы — это не требуется, так как мы будем анализировать и загружать файлы по мере их выбора.

При желании вы можете скрыть элемент ввода файла, если поддерживается перетаскивание файла. Лично я предпочитаю предлагать оба варианта, так как перетаскивание вызывает ряд проблем с удобством использования.

Проверка метода XMLHttpRequest.upload предотвращает проблемы в Opera. Браузер поддерживает File, FileList и FileReader, но не перетаскивает события или XMLHttpRequest2. Поэтому он может отображать информацию о файле, но мы не хотим показывать элемент #filedrag или удалять кнопку отправки.

Изменение стиля удаления файла

Мало кто сталкивался с проблемой перетаскивания файлов в веб-браузере. На самом деле, опытные веб-пользователи могут не считать это невозможным. Поэтому мы использовали элемент, который гласит «перетащите файлы сюда». Мы также хотим указать, когда файл был перетащен в местоположение #filedrag, изменив его стиль:

 
// file drag hover
function FileDragHover(e) {
	e.stopPropagation();
	e.preventDefault();
	e.target.className = (e.type == "dragover" ? "hover" : "");
}

Анализ удаленных или выбранных файлов

Мы используем одну и ту же функцию FileSelectHandler () независимо от того, был ли один или несколько файлов выбран с помощью «Обзор» или перетащен в местоположение #filedrag:

 
// file selection
function FileSelectHandler(e) {

	// cancel event and hover styling
	FileDragHover(e);

	// fetch FileList object
	var files = e.target.files || e.dataTransfer.files;

	// process all File objects
	for (var i = 0, f; f = files[i]; i++) {
		ParseFile(f);
	}

}

Функция:

  1. Вызывает FileDragHover () для удаления стиля наведения и отмены событий браузера. Это важно, иначе браузер может попытаться отобразить файл.
  2. Извлекает объект FileList. Это может быть либо из поля ввода файла (e.target.files), либо из элемента #filedrag (e.dataTransfer.files).
  3. Наконец, функция перебирает все объекты File в FileList и передает ее в качестве аргумента функции ParseFile ()…
 
function ParseFile(file) {

	Output(
		"<p>File information: <strong>" + file.name +
		"</strong> type: <strong>" + file.type +
		"</strong> size: <strong>" + file.size +
		"</strong> bytes</p>"
	);
	
}

Функция выводит информацию, используя три основных свойства только для чтения, предоставляемых объектом File:

  • .name : имя файла (оно не включает информацию о пути)
  • .type : тип MIME, например, image / jpeg, text / plain и т. д.
  • .size : размер файла в байтах.

Пожалуйста, просмотрите демонстрационную страницу в Firefox, Chrome или Opera (без поддержки перетаскивания). Вы также можете скачать файлы, чтобы изучить код.

Мы покрыли много земли. В следующей статье мы узнаем, как открывать удаленные файлы с помощью HTML5 и JavaScript

Эта статья также была переведена на армянский язык

Если вам понравилось читать этот пост, вы полюбите Learnable ; место, чтобы узнать новые навыки и приемы у мастеров. Участники получают мгновенный доступ ко всем электронным книгам и интерактивным онлайн-курсам SitePoint, таким как HTML5 и CSS3 для реального мира .

Комментарии к этой статье закрыты. У вас есть вопрос о HTML5? Почему бы не спросить об этом на наших форумах ?