Загрузка нескольких изображений html

Элемент input в html 5, мультиаплоад

У элемента input в HTML 5 появился атрибут multiple, с помощью которого мы можем выбрать для загрузки несколько файлов. Этот атрибут принимает только одно значение «multiple», в живую будет выглядеть так:

Обратите внимание на name, мы явно в нем указали, что это массив.

Сразу появляется вопрос, какой браузер это новшество не понимает, ответ легко предсказуем, это семейство Internet Explorer. Начиная с 9 версии и ниже, они не поддерживают этот функционал и просто проигнорируют атрибут, искренне надеюсь что в финальной 10 версии они это поправят.
Кроме того что, мы дали пользователям загрузить сразу много файлов, мы должны позаботиться о них, и дать им возможность загрузит именно те файлы которые нам необходимы. И тут на помощь приходит еще один новый атрибут accept. Который принимает «MIME Media Types».

Такой записью мы говорим о том, что загружать можно только картинки, и в окне выбора файлов сработает фильтр, который будет показывать пользователю только графические типы файлов. Firefox и Safari игнорируют accept.

И снова у нас появляется проблема, пользователь пытается отправить форму, но он был настолько занят, что забыл заполнить данными наш input. Мы не должны давать ему повода нервничать и волноваться, и будем в такой ситуации использовать еще один новый атрибут.

Атрибут required, принимает строку «required», и делает поле обязательным для заполнения.

Как это будет работать, при попытке отправить форму с пустым input, появится предупреждение о ошибке с следующим текстом:

Firefox:
image
Chrome:
image
Opera:
image

К моему удивлению Safari не показал предупреждение, и отправил пустую форму. Выше на картинках показано как это выглядит в трех браузерах, в Chrome оно не сильно эстетично смотрится, но зато только он показал дополнение к ошибке которое взял из title элемента.

var inputFile = document.getElementById('input').files; // вернет объект FileList :

Где 0,1,2 это ключи загружаемых файлов.
Length, количество файлов.
Метод item() принимающий ключ файла.

Обратиться к файлу можно двумя способами:

// Первый способ var file = inputFile[0]; // Второй var file = inputFile.item(0); 
File : < constructor: File , fileName: 'image.png', // имя файла fileSize: 879394, // размер файла name: 'image.png', // имя файла size: 879394, // размер файла type: 'image/png', // MIME тип файла getAsBinary, getAsDataURL, getAsText, lastModifiedDate: 'Thu May 26 2001 21:34:48 GMT+0300 (Eastern Europe Daylight Time)' > 

У Оперы нет свойств fileSize, FileName но зато есть name и size. В Chrome, Firefox, Safari есть все четыре свойства.
Только в Chrome есть свойство lastModifiedDate.

  • getAsBinary: получить исходный код файла.
  • getAsDataURL: получить данные преобразованные в base64
  • getAsText: тут я каюсь, до сих пор не разобрался что это, и буду очень благодарен если разъясните мне.

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

Ресурс который мне помог узнать и понять вышеизложенное про новые возможности input .

Читайте также:  Проверка входных данных php

Источник

HTML5 File API: множественная загрузка файлов на сервер

Когда передо мной в очередной раз встала задача об одновременной загрузке нескольких файлов на сервер (без перезагрузки страницы, само собой), я стал блуждать по интернетам в поисках довольно корявого jQuery-плагина, который позволяет имитировать ajax-загрузку файла (того самого плагина, который со скрытым фрэймом: от java- и flash- плагинов сразу было решено отказаться). В процессе поиска я вспомнил, что в грядущем стандарте html 5 возможности по работе с файлами должны быть существенно расширены, и часть этих возможностей доступна уже сейчас. В итоге было решено опробовать их в действии.

Рассматривать возможности File API будем на примере одновременной загрузки нескольких картинок на сервер. В конце статьи приводится готовое решение, оформленное в виде jQuery-плагина.

  1. Независимость от внешних плагинов
  2. Возможность контролировать процесс загрузки и отображать информацию о нем (прогрессбар всегда добавляет терпения пользователю)
  3. Возможность прочитать файл и узнать его размер до начала загрузки (в нашем примере это дает нам возможность отсеять файлы, не содержащие изображений и показывать миниатюры картинок)
  4. Возможность выбрать сразу несколько файлов через стандартное поле выбора файла
  5. Возможность использовать интерфейс drag and drop для выбора файлов. Да-да, мы сможем перетаскивать файлы для загрузки прямо с рабочего стола или, например, из проводника!

Работающий пример можно увидеть по адресу http://safron.pro/playground/html5uploader/, ниже приведены только наиболее важные фрагменты кода.

Для начала разберемся с html-кодом. Нам понадобится дефолтный элемент input, контейнер для перетаскивания файлов и список ul, куда мы будем помещать миниатюрки изображений:

Ничего особенного, кроме того, что для элемента input указан атрибут multiple=»true» . Это необходимо для того, чтобы в стандартном диалоге выбора файлов можно было выделять их сразу несколько. Кстати, начиная с Firefox 4, разработчики браузера обещают, что ненавистные многим верстальщикам стандартные поля выбора файла можно будет скрывать, а диалог показывать, вызвав событие click для скрытого элемента.

Теперь перейдем к JavaScript (обратите внимание, что я использовал jQuery для упрощения манипуляций с DOM. Тот, кто по каким-либо причинам захочет отказаться от jQuery, сможет без труда переделать скрипты таким образом, чтобы обойтись без него). Сначала сохраним в переменных ссылки на html-элементы, снявшиеся в главных ролях. Далее определим обработчики событий для стандартного поля выбора файлов и для области, куда можно будет перетаскивать файлы.

 // Стандарный input для файлов var fileInput = $('#file-field'); // ul-список, содержащий миниатюрки выбранных файлов var imgList = $('ul#img-list'); // Контейнер, куда можно помещать файлы методом drag and drop var dropBox = $('#img-container'); // Обработка события выбора файлов в стандартном поле fileInput.bind( < change: function() < displayFiles(this.files); >>); // Обработка событий drag and drop при перетаскивании файлов на элемент dropBox dropBox.bind(< dragenter: function() < $(this).addClass('highlighted'); return false; >, dragover: function() < return false; >, dragleave: function() < $(this).removeClass('highlighted'); return false; >, drop: function(e) < var dt = e.originalEvent.dataTransfer; displayFiles(dt.files); return false; >>); 

И в том и в другом случае в обработчике мы получаем доступ к объекту FileList, который по сути представляет собой массив объектов File. Этот массив передается функции displayFiles(), текст которой приведен ниже.

 function displayFiles(files) < $.each(files, function(i, file) < if (!file.type.match(/image.*/)) < // Отсеиваем не картинки return true; >// Создаем элемент li и помещаем в него название, миниатюру и progress bar, // а также создаем ему свойство file, куда помещаем объект File (при загрузке понадобится) var li = $('').appendTo(imgList); $('').text(file.name).appendTo(li); var img = $('').appendTo(li); $('').addClass('progress').text('0%').appendTo(li); li.get(0).file = file; // Создаем объект FileReader и по завершении чтения файла, отображаем миниатюру и обновляем // инфу обо всех файлах var reader = new FileReader(); reader.onload = (function(aImg) < return function(e) < aImg.attr('src', e.target.result); aImg.attr('width', 150); /* . обновляем инфу о выбранных файлах . */ >; >)(img); reader.readAsDataURL(file); >); > 

Объект File содержит метаданные о файле, такие как его имя, размер и тип (в формате MIME, например, image/gif) соответственно в свойствах name, size и type. Для доступа же к содержимому файла существует специальный объект FileReader.

Читайте также:  Request python get file

Внутри функции displayFiles() мы проходимся по переданному массиву файлов и сначала отсеиваем те, которые не являются изображениями. Далее для каждого изображения создается элемент списка li, куда помещается пустой пока элемент img (обратите внимание, что в кажом элементе li также создается свойство file, содержащее соответствующий объект). После чего создается экземпляр FileReader и для него определяется обработчик onload, в котором данные передаются прямо в атрибут src созданного ранее элемента img. Метод readAsDataURL() объекта FileReader принимает параметром объект File и запускает чтение данных из него. В результате для всех выбранных через стандартное поле или перетащенных прямо в браузер картинок, мы видим их миниатюры (искусственно уменьшенные до 150 пикселей).

Что еще осталось сделать? Осталось только реализовать саму загрузку всех выбранных файлов на сервер. Для этого создадим какую-нибудь кнопку или ссылку, при нажатии на которую останется только пробежаться по всем созданным элементам li, прочитать их свойство file и передать в функцию uploadFile(), текст которой приведен ниже. Отмечу, что здесь для упрощения я реализовал загрузку через функцию, а в реальном примере, расположенном по адресу http://safron.pro/playground/html5uploader/, я собрал все действия по загрузке в объект uploaderObject, при создании которого можно передать дополнительные параметры, такие как функции обратного вызова для получения информации о процессе загрузки.

function uploadFile(file, url) < var reader = new FileReader(); reader.onload = function() < var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", function(e) < if (e.lengthComputable) < var progress = (e.loaded * 100) / e.total; /* . обновляем инфу о процессе загрузки . */ >>, false); /* . можно обрабатывать еще события load и error объекта xhr.upload . */ xhr.onreadystatechange = function () < if (this.readyState == 4) < if(this.status == 200) < /* . все ок! смотрим в this.responseText . */ >else < /* . ошибка! . */ >> >; xhr.open("POST", url); var boundary = "xxxxxxxxx"; // Устанавливаем заголовки xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); xhr.setRequestHeader("Cache-Control", "no-cache"); // Формируем тело запроса var body = "--" + boundary + "\r\n"; body += "Content-Disposition: form-data; name='myFile'; filename='" + file.name + "'\r\n"; body += "Content-Type: application/octet-stream\r\n\r\n"; body += reader.result + "\r\n"; body += "--" + boundary + "--"; if(xhr.sendAsBinary) < // только для firefox xhr.sendAsBinary(body); >else < // chrome (так гласит спецификация W3C) xhr.send(body); >>; // Читаем файл reader.readAsBinaryString(file); > 

Здесь создается экземпляр уже знакомого нам объекта FileReader, точно так же, как и выше; ему присваивается обработчик события onload, в котором создается XMLHttpRequest (к сожалению, пока нельзя воспользоваться ajax-интерфейсом jQuery, поскольку там еще не предусмотрена загрузка файлов). В XMLHttpRequest второй версии появилось свойство upload, содержащее объект-загрузчик, который может обрабатывать события progress, load и error (подробнее см. http://www.w3.org/TR/XMLHttpRequest2/#xmlhttprequesteventtarget). В примере выше показана только обработка события progress. Далее присваиваем обработчик завершения запроса самому реквесту (в отличие от событий объекта-загрузчика он вызывается уже тогда, когда все данные загружены и ответ от сервера получен), добавляем два дополнительных заголовка и формируем тело запроса, читая данные из свойства result объекта FileReader. После этого загрузка запускается. Отмечу только, что по нынешней спецификации W3C подразумевается, что метод send() объекта XMLHttpRequest может принимать в параметре бинарные данные, что успешно и реализовано в Google Chrome, однако в Firefox сделано по-своему, через особый метод sendAsBinary(). Поэтому перед началом отправки проверяем, определен ли метод sendAsBinary() в объекте реквеста, и, если да, используем его.

Читайте также:  hello php!

Вот, собственно, и все. С нетерпением ждем утверждения и распространения html 5!

Кое-какие ссылки
  1. http://safron.pro/playground/html5uploader/ — работающий пример того, что описывалось выше (плюс еще кое-что)
  2. http://safron.pro/playground/html5uploader/full.zip — весь код целиком в архиве
  3. http://html5test.com — проверка браузеров на соответсвие html 5 (очень наглядно)
  4. http://playground.html5rocks.com — площадка для экпериментов с кодом от Google (ее интерфейс будет знаком тем, кто использовал многочисленные API Google)

UPD
Для упрощения использования всего вышеизложенного, был создан JQuery-плагин. При помощи него можно загружать файлы через File API там, где это возможно, и реализовать замену (например, обычную отправку формы) там, где нет. По просьбам трудящихся и соотносясь с замечаниями комментаторов, была добавлена загрузка через объект FormData в браузерах, которые его поддерживают (Chrome, Safari 5+, FF 4+). В самом верху файла с плагином есть описание параметров, методов, а также краткие примеры использования. Более полный пример использования можно увидеть здесь (это изначальный пример из этой статьи, только переделанный на использование плагина, его полный код, включая серверную часть, можно скачать здесь [see UPD2]).

Использованные источники
  1. https://developer.mozilla.org/en/using_files_from_web_applications — статья о файловом интерфейсе на сайте девелоперов Mozilla
  2. https://developer.mozilla.org/En/XMLHttpRequest/Using_XMLHttpRequest — cтатья об использовании XMLHttpRequest там же
  3. http://www.w3.org/TR/FileAPI/ — текущая спецификация File API на сайте W3C
  4. http://www.w3.org/TR/XMLHttpRequest2/ — текущая спецификация XMLHttpRequest там же

UPD2
По просьбе пользователя glebovgin плагин был доработан таким образом, чтобы можно было отправлять не только непосредственно объект File, но также Blob-данные (объект Blob). Это может быть полезно, если есть необходимость отправлять на сервер, например, содержимое canvas, ну или просто вручную сгенерированные данные.

В демке (которая переехала немного на другой адрес) был добавлен пример отправки картинки из canvas. На данный момент эта возможность работает в FF, Chrome, IE10.

Исходный код ныне доступен на GitHub. Замечания, предложения, улучшения приветствуются!

Источник

Оцените статью