Перетаскивание файлов с рабочего стола в браузер — одна из главных целей интеграции веб-приложений. Это первая из четырех статей, в которой рассказывается, как:
- включить перетаскивание файла на элемент веб-страницы
- анализировать удаленные файлы в JavaScript
- загружать и анализировать файлы на клиенте
- асинхронно загружать файлы на сервер, используя XMLHttpRequest2
- покажите графический индикатор выполнения во время загрузки
- Используйте прогрессивное улучшение, чтобы убедиться, что ваша форма загрузки файлов работает в любом браузере (хорошая новость для всех вас, поклонников IE6!)
- закодируйте его на обычном 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 ():
- Устанавливает прослушиватель события «change» для элемента ввода файла.
- Отображает элемент #filedrag.
- Устанавливает прослушиватели событий «dragover» и «dragleave» для изменения стиля элемента #filedrag.
- Устанавливает прослушиватель события drop для элемента #filedrag.
- Скрывает кнопку отправки формы — это не требуется, так как мы будем анализировать и загружать файлы по мере их выбора.
При желании вы можете скрыть элемент ввода файла, если поддерживается перетаскивание файла. Лично я предпочитаю предлагать оба варианта, так как перетаскивание вызывает ряд проблем с удобством использования.
Проверка метода 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);
	}
}
Функция:
- Вызывает FileDragHover () для удаления стиля наведения и отмены событий браузера. Это важно, иначе браузер может попытаться отобразить файл.
- Извлекает объект FileList. Это может быть либо из поля ввода файла (e.target.files), либо из элемента #filedrag (e.dataTransfer.files).
- Наконец, функция перебирает все объекты 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? Почему бы не спросить об этом на наших форумах ?