Статьи

Загрузка файлов и события Progress с HTML5 XmlHttpRequest Level 2


Спецификация XmlHttpRequest Level 2 добавляет несколько улучшений к объекту XmlHttpRequest. На прошлой неделе я писал в блоге о
перекрестных запросах и о том, чем они отличаются от
подхода Flash \ Silverlight . С помощью спецификации уровня 2 можно загрузить файл на сервер, передав объект файла в метод send. В этом посте я попытаюсь изучить загрузку файла с использованием XmlHttpRequest 2 в сочетании с событиями прогресса. Я также предоставлю описание нового тега HTML5 — 
ход выполнения, который можно обновлять во время загрузки файла на сервер. И, конечно, некоторый код ColdFusion, который покажет, как файл принимается и сохраняется в каталоге сервера.



Тег прогресса:

HTML5 ввел в язык несколько новых элементов и один из них —
 элемент
прогресса . Этот элемент используется для отображения индикатора выполнения на веб-странице. Этот тег удобен для описания любой незавершенной работы. Его можно использовать для описания хода выполнения трудоемкой задачи.
 Элемент
прогресса имеет два атрибута:
значение и
макс .
Значение атрибута используется для указания текущего значения прогресса и
максимальный атрибут используется для описания значения завершения.

 <progress id="progressBar" value="0" max="100">  
 </progress>  

События хода выполнения XmlHttpRequest

. Единственным прослушивателем событий, который был доступен с
XmlHttpRequest, был
прослушиватель событий readystatechange . Теперь, с появлением HTML5, в интерфейс XmlHttpRequest было добавлено несколько прослушивателей событий 
— 
loadstart ,
progress ,
load ,
abort ,
error ,
timeout и
loadend .
Loadstart событие запускается , когда запрос инициируется клиентом. 
Прогресс  событие инициируется после того
, как
loadstart событие было послано.

В этом примере я попытаюсь загрузить файл (текст, изображение, mp3) с помощью
XmlHttpRequest и показать прогресс для него, обновив 
индикатор выполнения  (тег прогресса) с помощью
обработчика событий
прогресса . С помощью спецификации уровня 2 теперь можно передавать 
объекты ArrayBuffer ,
Blob ,
File и
FormData в метод send.
Ввода тегов с типом
файла может использоваться , чтобы выбрать файл , который должен быть загружен на сервер (<входной тип = «файл» ID = «FileUpload»>). Как только файл выбран, на сервер может быть сделан запрос POST, а объект файла может быть передан в качестве аргумента методу send:

 function uploadFile(){  
         var filesToBeUploaded = document.getElementById("fileControl");  
         var file = filesToBeUploaded.files[0];  
         var xhrObj = new XMLHttpRequest();  
         xhrObj.upload.addEventListener("loadstart", loadStartFunction, false);  
         xhrObj.upload.addEventListener("progress", progressFunction, false);  
         xhrObj.upload.addEventListener("load", transferCompleteFunction, false);  
         xhrObj.open("POST", "upload.cfm", true);  
         xhrObj.setRequestHeader("Content-type", file.type);  
         xhrObj.setRequestHeader("X_FILE_NAME", file.name);  
         xhrObj.send(file);  
 }  

Как видно из приведенного выше кода, прослушиватели событий добавляются для
событий loadstart ,
progress и
load . Эти события добавляются для атрибута загрузки
объекта
XmlHttpRequest .
Content-Type заголовка устанавливается на значение
file.type . Это необходимо для того, чтобы сервер знал тип передаваемого файла MIME. Также указывается заголовок X_FILE_NAME со значением
file.name .
Файл объект затем передаются
посыл способу
XmlHttpRequest объекта.
loadstart

Событие инициируется, когда инициируется запрос на отправку файла на сервер. Как только эта функция отправлена,
запускается событие
progress , указывающее, что файл загружается на сервер:

  function progressFunction(evt){  
         var progressBar = document.getElementById("progressBar");  
         var percentageDiv = document.getElementById("percentageCalc");  
         if (evt.lengthComputable) {  
           progressBar.max = evt.total;  
           progressBar.value = evt.loaded;  
           percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";  
         }  
 }  

Прогресс событие инициируется , как и когда некоторые данные передаются на сервер. Это зависит от размера файла, который передается. Функция progressFunction, определенная выше, принимает аргумент типа
ProgressEvent .
ProgressEvent Интерфейс определяет атрибуты —
lengthcomputable ,
нагруженные и
всего .
Lengthcomputable атрибут используется для поиска , является ли прогресс индетерминисти- или детерминированным один. В этом случае размер загружаемого файла известен, и, следовательно, для
атрибута
lengthcomputable будет установлено значение true. Другие атрибуты
загружены и
всегоиспользуются для указания количества загруженных байтов от общего количества байтов. Эти данные затем используются для обновления
значения атрибутов тега
прогресса и
макс .
Код на стороне сервера: Код на стороне сервера настолько прост, насколько может быть:

 <cfset headerData = getHTTPRequestData().headers>  
 <cfset content = getHTTPRequestData().content>  
 <cfset filePath = expandPath(".") & "/Uploaded/" & headerData.X_FILE_NAME >  
 <cfset fileWrite(filePath,content)>  

Заголовок X_FILE_NAME будет содержать имя файла, отправляемого клиентом. Содержимое файла доступно в данных запроса, доступ к нему осуществляется с помощью
getHTTPRequestData (). Content .