Прежде всего, позвольте мне использовать эту диаграмму, чтобы объяснить, как можно добиться асинхронной загрузки файлов :
Извините. Я отключил один из своих доменов, и изображение исчезло. Хотя это был действительно красивый образ. Это было до того, как я узнал, что Stack Overflow позволяет загружать изображения через Imgur.
Как видите, фокус состоит в том, чтобы позволить HTTP-ответу загружаться в скрытый элемент IFRAME вместо самой страницы. (Это делается путем установки свойства target
элемента FORM при отправке FORM с помощью JavaScript.)
Это работает. Однако проблема, с которой я столкнулся, заключается в том, что серверный сценарий находится в другом домене . FORM-submit - это междоменный HTTP-запрос. Теперь в серверном скрипте включен CORS, который дает моей веб-странице права на чтение данных ответа HTTP-запросов, сделанных с моей страницы, в этот скрипт, но это работает, только если я получаю HTTP-ответ через Ajax, эрго, JavaScript.
Однако в этом случае ответ направлен на элемент IFRAME. И как только ответ XML попадает в IFRAME, его URL-адрес будет сценарием удаления, например http://remote-domain.com/script.pl
.
К сожалению, CORS не охватывает этот случай (по крайней мере, мне кажется) - я не могу прочитать содержимое IFRAME, поскольку его URL-адрес не соответствует URL-адресу страницы (другой домен). Я получаю эту ошибку:
Небезопасная попытка JavaScript получить доступ к фрейму с URL-адресом hxxp: //remote-domain.com/script.pl из фрейма с URL hxxp: //my-domain.com/outer.html. Домены, протоколы и порты должны совпадение.
А поскольку содержимое IFRAME является XML-документом, внутри IFRAME нет кода JavaScript, который мог бы использовать postMessage
или что-то в этом роде.
Итак, мой вопрос: Как мне получить содержимое XML из IFRAME?
Как я сказал выше, я могу получать междоменные HTTP-ответы напрямую (с включенным CORS), но мне кажется, что я не могу читать междоменные ответы HTTP-ответы после их загрузки в IFRAME.
И, как если бы этот вопрос недостаточно неразрешим, позвольте мне исключить эти решения :
easyXDM и аналогичные методы, которые требуют конечной точки на удаленный домен,
изменение ответа XML (для включения элемента SCRIPT),
прокси на стороне сервера - я понимаю, что в моем домене мог бы быть сценарий на стороне сервера, который мог бы служить прокси.
Итак, помимо этих двух решений, можно ли это сделать?
Оказывается, можно подделать XHR-запрос (Ajax-запрос), который имитирует использует multipart / form-data
FORM submit (который используется на изображении выше для загрузки файла на сервер).
Хитрость заключается в использовании конструктора FormData
- чтение эта статья Mozilla Hacks для получения дополнительной информации.
Вот как вы это делаете:
// STEP 1
// retrieve a reference to the file
// elements have a "files" property
var file = input.files[0];
// STEP 2
// create a FormData instance, and append the file to it
var fd = new FormData();
fd.append('file', file);
// STEP 3
// send the FormData instance with the XHR object
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://remote-domain.com/script.pl', true);
xhr.onreadystatechange = responseHandler;
xhr.send(fd);
Вышеупомянутый метод выполняет асинхронную загрузку файлов, которая эквивалентна обычной загрузке файлов, описанной на изображении выше и достигается путем отправки этой формы: