Подтвердить что ты не робот

Загрузка Amazon S3 через iframes

Вздох, мы вернемся к этому. Я могу с легкостью использовать CORS на любом достаточно приличном браузере, чтобы напрямую загружать файлы в мой ковш AWS S3. Но (он шел), с IE я должен вернуться к iframes. Легко, настройте скрытый iframe, создайте форму, установите ее цель в iframe name/id, submit form. Если загрузка выполнена успешно, Iframe перенаправляется на указанный мной URL-адрес, и я могу получить доступ к тому, что мне нужно. Но если возникает ошибка, так как Iframe теперь находится в домене AWS, у меня не будет доступа к содержимому XML ошибки. Infact, я даже не знаю, что произошла ошибка.

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

Может ли кто-нибудь объяснить мне, как достичь этого мифического решения? Похоже, что загрузчик файлов jQuery от Blueimp решает это, но, по словам Бога, код настолько jQueryified, что я не смог получить его суть.

Редактирование для ясности

  • IE < 10 не имеет API FileReader.
  • Из-за 1 я не могу использовать XDomainRequest для отправки файла на S3
  • Итак, используйте iframe и отправьте его вместе с полной формой на S3
  • В случае успеха AWS перенаправляет страницу на сервер, которая читает заголовки и затем возвращает ответ стиля JSONP, который может быть прочитан скриптами на клиенте (страница перенаправления может указывается мной).
  • Если при ошибке все, что я могу сделать прямо сейчас, это ждать истечения времени ожидания, а затем консольного журнала
    идентификатор IFRAME и всплывающее предупреждение, чтобы пользователь мог запросить идентификатор iframe по ID,
    прочитайте XML-контент DAMN, определите ошибку AWS, а затем повторите попытку (я саркастичен..)
4b9b3361

Ответ 1

Почти все, что вам нужно знать о том, как плагин загрузки файла jQuery делает загрузку iframe, находится в плагине iframe Transport (наряду с поддержкой result.html).

В качестве введения вы можете прочитать свои инструкции для пользователей на странице Перекрестный домен загружаемых, в частности, Транспортировка транспорта iframe между сайтами. (Обратите внимание, что в соответствии с их страницей Поддержка браузера тонкости, такие как процесс загрузки, не поддерживаются для IE < 10, поэтому я не буду рассматривать их с использованием транспорта iframe, по крайней мере без значительных усилий.)

(Кроме того, я не считаю, что реализация S3-загрузки с использованием плагина File Upload имеет доступ к XML-содержимому ошибки загрузки файла)

Плагин Iframe Transport добавляет новый метод "транспорта" Ajax для jQuery и не относится к плагину загрузки файлов. Вы можете прочитать документацию для jQuery.ajaxTransport(), чтобы понять API, который jQuery предоставляет для добавления нового транспорта.


Я попытаюсь обобщить, что делает плагин Iframe Transport, и как он относится к загрузке файлов в Amazon S3:

  • Когда запускается загрузка файла, вызывается функция send(). Эта функция:

    • Создает скрытый элемент формы

    • Создает элемент iframe с src="javascript:false;" и связывает обработчик события load с iframe

    • Добавляет iframe в скрытую форму и добавляет скрытую форму в документ.

  • Когда создается iframe и загружается "страница", вызывается обработчик события load. Обработчик:

    • Очищает себя от iframe и связывает другой load обработчик событий

    • Настраивает скрытую форму:

      • Форма action будет URL-адресом для ведра S3

      • Форма target установлена ​​в iframe, так что ответ сервера загружается в iframe

      • Другие поля, например. AWSAccessKeyId. В частности, success_action_redirect устанавливается на URL-адрес result.html на вашем сервере, например. http://example.org/result.html?%s.

        Обычно токен %s должен быть заменен результатами загрузки по серверному коду, но с S3 это может быть жестко закодировано с успешным значением вашего кода, так как Amazon будет перенаправлять на этот URL-адрес, только если загрузка выполнена успешно.

      • Поля ввода файла из исходной формы перемещаются в скрытую форму, а клонированные поля остаются в исходном поле "

    • Отправляет скрытую форму

    • Перемещает поля ввода файла обратно в исходную форму, заменяя клонированные поля

  • Файл загружаются на S3. В случае успеха Amazon перенаправляет iframe на URL success_action_redirect. Если не удалось, Amazon возвращает ошибку, которая также загружается в iframe.

  • Вызывается обработчик событий iframe load. Обработчик:

    • Пытается сохранить ссылку на объект iframe document. Если загрузка файла не удалась, обработчик сохраняет вместо этого undefined.

    • Вызывает полный обратный вызов с кодом успеха и ссылкой на объект iframe document (или undefined)

    • Удаляет скрытую форму (и iframe)

  • Прежде чем управление будет возвращено вашему коду, объект iframe document передается в конвертер (внизу плагин iframe Transport), в зависимости от того, какой тип данных вы ожидали. Конвертер извлекает эти данные из объекта document и возвращает его (или undefined, если загрузка файла не удалась) для вашего обратного вызова.

  • Вызывается ваш обратный вызов (successи/или complete), который передается jQuery.ajax()). Код успеха всегда возвращается плагином, поэтому любой обратный вызов error не запускается.

    Если данные, переданные на ваш обратный вызов (-ы), являются значением, которое вы включили в success_action_redirect, то загрузка файла прошла успешно. Если данные undefined, то загрузка файла не удалась.


Обновление: Если страница XML ошибки находится в том же самом начале, что и ведро S3, тогда другая страница из ведра S3, загруженная в другой iframe, может получить доступ к исходному содержимому iframe (поскольку они из того же источника). Ваша главная страница может связываться с этим вторым iframe, используя postMessage() (или easyXDM FlashTransport, если вам нужно поддерживать IE6/7).

Ответ 2

Эта проблема, обеспечивающая точную обратную связь с пользователями, использующими браузеры без поддержки FileReader или FormData, очень беспокоила меня. Я потратил целых 3 дня, пытаясь придумать решение и, наконец, придумал что-то почти ничего.

Давайте рассмотрим факты:

  • Браузер: IE8/9//худший шанс быть любым другим браузером без поддержки FileReader
  • Поведение при загрузке: нам нужно, чтобы он был "Ajax" по причинам UX.
  • Toolbelt: Загрузка файла jQuery *

Хорошо, тогда нет другого способа загрузки файла, кроме использования iframe. Правильно?

Итак, загрузка файла jQuery с использованием jQuery Iframe Transport как @jeferry_to так хорошо описывает инструмент для задания.

* На самом деле инструмент/плагин ничего не меняет.

Что теперь?

Ну... нам нужно получить доступ к ответу S3 внутри транспортного фрейма. Но мы не можем, потому что это в другом домене. Поэтому мы решили справиться с этим, используя этот трюк, включающий второй iframe.

Настройка:

  • TopFrame, наша страница (www.myhost.com)
  • iframe TransportFrame (s3.amazonaws.com), автоматически созданный плагином - содержит ответ S3
  • iframe XDMFrame (s3.amazonaws.com), получает доступ к транспортному фрейму при заказе, захватывает ответ и доставляет его в TopFrame

Сценарий:

Прежде всего нам нужно изменить jQuery iframe Transport, чтобы он не удалял автоматически сгенерированную форму и транспортный фрейм. Нам нужно сделать эту причину. #postMessage, который будет использоваться позже, является асинхронным по своей природе, и мы не хотим, чтобы iframe ушел к тому времени, когда мы пытаемся получить к нему доступ.

  • на TopFrame мы загружаем файл в S3using загрузку файла jQuery. Теперь мы хотим убедиться, что оно было загружено и получить сообщение об ошибке.
  • TopFrame отправляет междоменное сообщение в XDMFrame с использованием #postMessage, предоставляя имя TransportFrame. Это сообщение на самом деле говорит: "Эй, проверьте содержимое iframe X", и когда вы отправите их мне обратно.
  • XDMFrame затем делает что-то вроде top.frames['iframe X'].document.documentElement для доступа к тевому содержимому TransportFrame, строит их и отправляет обратно в TopFrame через #postMessage.
  • TopFrame получает сообщение, показывает правильную обратную связь с пользователем и удаляет форму и iframe влево из-за изменения jQuery Iframe Transport.

Хорошо, теперь все должно работать, потому что все делается книгой.

Нахх, ты даже не должен беспокоиться.

Вы видите... если вы заставите современный браузер использовать транспорт iframe вместо XHR2, то вышеупомянутое решение действительно будет работать как шарм.

Однако это бессмысленно. Мы хотим, чтобы он работал в IE8 + 9.

Ну... в IE8/9 он иногда работает, иногда это не так. Обычно это не так.

Почему? Из-за дружественных IE сообщений об ошибках HTTP. О да, вы прекрасно читали.

В случае ошибки S3 отвечает статусом ошибки HTTP в зависимости от ошибки (400, 403 и т.д.). Теперь, в зависимости от состояния и длины ответа, как показано здесь, IE отбрасывает ответ S3 и заменяет его дружественным сообщением об ошибке. Чтобы преодолеть это, вы должны убедиться, что ответ всегдa > 512 байт. В этом случае вы не можете гарантировать что-либо подобное, потому что вы не контролируете ответ. S3 и типичные ошибки меньше 512 байт.

Короче:

трюк iframe работает на тех браузерах, которые ему не нужны, и не на тех, кто это делает.

К сожалению, я не могу думать ни о чем другом, так что случай закрыт для меня сейчас.

Ответ 3

Подводя итог моему ответу в комментариях: IE поддерживает CORS с некоторыми ограничениями: http://www.html5rocks.com/en/tutorials/cors/

и эта реализация прямой загрузки на S3 выглядит намного проще, чем jquery fileupload и ее не в jquery: http://codeartists.com/post/36892733572/how-to-directly-upload-files-to-amazon-s3-from-your

Надеюсь, это поможет!

Ответ 4

AS для сценария postMessage, возможно, iframe должен содержать простой javascript

[edit] для iframe, принятого с помощью errormessage

IFRAME script

window.document.onload = function(e){ 
    window.parent.postMessage(document, '*'); //replace '*' with your parent if possible   
}
// just to get the proper document for the parent to target me
window.addEventListener('message',function(e) {
    if (e.domain == 'example.com') { // the domain of your parent frame
        if (e.data == "Salute") {
            window.parent.postMessage("I'm here", '*'); //replace '*' with your parent too
        }
    }
});

Теперь родитель прекрасно знает iFrame и может отслеживать его статус (в зависимости от того, отвечает ли он на простой postMessage)

PARENT script

var iFrameTarget;
var iFrameTakenOver = false;
var timer;
window.addEventListener('message',function(e) {
    if (e.domain == 'example.com') { // the domain of your iframe
        if (e.data) { // e.data contains the iframe document
            if(typeof(e.data) =='object')
                iFrameTarget = e.source;
            elseif(e.data == "I'm here")
            {
                iFrameTakenOver = false;
            }
            timer =setInterval(call_iFrame(),5000); // check iFrame presence in 5 seconds
        }
    }
});

function call_iFrame() {
    iFrameTarget.postMessage('Salute');
    iFrameTakenOver = true;
}

IF iframe не отвечает им "код". iFrameTakenOver будет постоянно установлен на ложную проверку, которая проверит, произошла ли ошибка.