Пример 18.9. Выгрузка файла посредством запроса HTTP POST
// Отыскивает все элементы <input type=”file"> с атрибутом data-uploadto
// и регистрирует обработчик onchange, который автоматически отправляет
// выбранный файл по указанному URL-адресу "uploadto". Ответ сервера игнорируется.
whenReady(function { // Вызвать эту функцию после загрузки документа
var elts = document.getElementsByTagName("input”); //
Все элементы input
for(var і = 0; і < elts.length; i++) { // Обойти в цикле
var input = elts[i];
if (input.type !== ’'file") continue; // Пропустить все, кроме
// элементов выгрузки файлов
var url = input.getAttribute("data-uploadto"); // Адрес выгрузки
if (!url) continue; // Пропустить элементы без url
input.addEventListener("change", function { // При выборе файла
var file = this.files[0]; // Предполагается выбор единственного файла
if (!file) return; // Если файл не выбран, ничего не делать
var xhr = new XMLHttpRequest; // Создать новый запрос
xhr.open("POST", url); // Методом POST на указанный URL
xhr.send(file); // Отправить файл в теле запроса
}, false);
}
});
Как будет показано в разделе 22.6, тип
File
является подтипом более общего типа
Blob
. Спецификация «ХНН2» позволяет передавать методу
send
произвольные объекты
Blob
. Свойство
type
объекта
Blob
в этом случае будет использоваться для установки заголовка «Content-Type», если он не будет определен явно. Если потребуется выгрузить двоичные данные, сгенерированные клиентским сценарием, можно воспользоваться приемами преобразования данных в объект
Blob
, демонстрируемыми в разделах 22.5 и 22.6.3, и передавать в виде тела запроса этот объект.
18.1.3.5. Запросы с данными в формате multipart/form-data
Когда наряду с другими элементами HTML-формы включают элементы выгрузки файлов, броузер не может использовать обычный способ представления данных форм и должен отправлять формы, используя специальное значение «multipart/form-data» в заголовке «Content-Type». Этот формат связан с использованием длинных «граничных» строк, делящих тело запроса на несколько частей. Для текстовых данных можно вручную создать тело «multipart/form-data» запроса, но это довольно сложно.
Спецификация «ХНН2» определяет новый прикладной интерфейс
FormData
, упрощающий
создание тела запроса, состоящего из нескольких частей. Сначала с помощью конструктора
FormData
создается объект
FormData
, а затем вызовом метода
append
этого объекта в него добавляются отдельные «части» (которые могут быть строками или объектами
File
и
Blob
). В заключение объект
FormData
передается методу
send.
Метод
send
определит соответствующую строку, обозначающую границу, и установит заголовок «Content-Type» запроса. Пример 18.10 демонстрирует использование объекта
FormData
, с которым мы еще встретимся в примере 18.11.
Пример 18.10. Отправка запроса с данными в формате multipart/form-data
function postFormData(url, data, callback) {
if (typeof FormData === "undefined")
throw new Error("Объект FormData не реализован");
var request = new XMLHttpRequest; // Новый HTTP-запрос
request.open("POST", url); // Методом POST на указанный URL
request.onreadystatechange = function { // Простой обработчик,
if (request.readyState === 4 && callback) // При получении ответа
callback(request); // вызвать указанную функц.
};
var formdata = new FormData;
for(var name in data) {
if (!data.hasOwnProperty(name)) continue; // Пропустить унасл. св-ва
var value = data[name];
if (typeof value === "function”) continue; // Пропустить методы
// Каждое свойство станет отдельной "частью" тела запроса.