Загрузка 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, что я не смог получить его суть.

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

  1. IE<10 does not have a FileReader API.
  2. Because of 1, I cannot use an XDomainRequest to send a file to S3
  3. So use an Iframe and post that along with a complete form to S3
  4. If successful, AWS redirects to a page on server, which reads the headers and
    then returns a JSONP style response that can be read by scripts on client (redirect page can
    be specified by me).
  5. If on error, all I can do right now is wait for a timeout to expire and then console log
    an IFRAME ID, and popup an alert so that the user can then query for the the iframe by ID,
    read the DAMN xml content, figure out the AWS specified error, and then retry (I'm being sarcastic..)
22
nl ja de
@ d33pika - Это снова не будет работать на IE (ссылка, которую вы опубликовали)
добавлено автор Jibi Abraham, источник
@ d33pika - я имел в виду реализацию, как в исходном коде, а не фактическое использование. Но все равно спасибо
добавлено автор Jibi Abraham, источник
@Henrik Я должен посмотреть на это. Будет опубликован через десять минут
добавлено автор Jibi Abraham, источник
@ d33pika есть также проблема NO CORS в IE
добавлено автор Jibi Abraham, источник
@ d33pika - он использует волшебный плагин jQuery для загрузки файлов. Я упомянул в вопросе, что задача извлечь из этой плагины очень много логики очень сложна
добавлено автор Jibi Abraham, источник
@JibiAbraham: Ну, у IE был CORS с версии 8, но, придерживаясь традиции, он, очевидно, решил пойти своим путем. XDomainRequest - Ограничения, Ограничения и способы обхода
добавлено автор Henrik, источник
добавлено автор d33pika, источник
Почему CORS не работает для IE? Я получил один, используя jQuery fileupload плагин, но я не тестировал его на IE. Это сообщение blog.appharbor.com/2013/01/10/… , похоже, указывает, что он будет работать на IE
добавлено автор d33pika, источник
xhr может работать с IE за некоторыми исключениями: html5rocks.com/en/tutorials/cors
добавлено автор d33pika, источник
Основной плагин не настолько сложный: github.com/blueimp/jQuery- File-Upload/wiki/Basic-plugin . Проверьте это.
добавлено автор d33pika, источник

4 ответы

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

As an introduction, you may want to read their user instructions on their Cross domain uploads wiki page, specifically the Cross-site iframe transport uploads section. (Note that according to their Browser support page, niceties like upload progress are not supported for IE <10, so I wouldn't consider these possible using the iframe transport, at least without significant effort.)

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

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


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

  1. When a file upload is triggered, the send() function is called. This function:

    • Creates a hidden form element

    • Creates an iframe element with src="javascript:false;", and binds a load event handler to the iframe

    • Appends the iframe to the hidden form, and appends the hidden form to the document.

  2. When the iframe is created and its "page" loaded, its load event handler is called. The handler:

    • Clears itself from the iframe, and binds another load event handler

    • Configures the hidden form:

      • The form's action will be the URL for the S3 bucket

      • The form's target is set to the iframe, so that the server response is loaded in the iframe

      • Other fields, e.g. AWSAccessKeyId, are added. Specifically, success_action_redirect is set to the URL of result.html on your server, e.g. http://example.org/result.html?%s.

        Normally, the %s token should be replaced with the upload results by server-side code, but with S3 this can be hard-coded with a success value by your code, since Amazon will redirect to this URL only if the upload succeeded.

      • File input fields from the original form are moved into the hidden form, with cloned fields left in the original fields' place

    • Submits the hidden form

    • Moves the file input fields back into the original form, replacing the cloned fields

  3. The file(s) are uploaded to S3. If successful, Amazon redirects the iframe to the success_action_redirect URL. If not successful, Amazon returns an error, which is also loaded in the iframe.

  4. The iframe's load event handler is called. The handler:

    • Tries to save a reference to the iframe's document object. If the file upload failed, the handler saves an undefined instead.

    • Calls the complete callback with a success code and a reference to the iframe's document object (or undefined)

    • Removes the hidden form (and iframe)

  5. Before control is returned to your code, the iframe's document object is passed to a converter (at the bottom of the Iframe Transport plugin), depending on what type of data you were expecting. The converter extracts that data from the document object and returns it (or undefined if the file upload failed) to your callback(s).

  6. Your callback(s) (success and/or complete as passed to jQuery.ajax()) is called. A success code is always returned by the plugin, and so any error callback will not be triggered.

    If the data passed to your callback(s) is the value you included in the success_action_redirect, then the file upload succeeded. If the data is undefined, then the file upload failed.


Update: If the error xml page stays on the same origin as the S3 bucket, then another page from the S3 bucket, loaded into another iframe, can access the original iframe's content (because they are from the same origin). Your main page can communicate with this second iframe using postMessage() (or easyXDM's FlashTransport, if you need to support IE6/7).

19
добавлено
Я дам этот снимок, у меня есть все, кроме ошибки обработки, сообщит вам, tx
добавлено автор Jibi Abraham, источник
«Пытается сохранить ссылку на объект документа iframe» - это может вызвать нечеткую ошибку, не так ли?
добавлено автор Jibi Abraham, источник

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

Давайте перейдем к фактам:

  • Browser: IE8/9//thin chance of being any other browser with no FileReader support
  • Upload Behavior: we need it to be "Ajax" for UX reasons
  • Toolbelt: jQuery File Upload*

Хорошо, тогда нет другого способа загрузки файла, кроме использования 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 ушел к тому времени, когда мы пытаемся получить к нему доступ.

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

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

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

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

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

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

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

In case of an error, S3 responds with an HTTP error status depending on the error (400, 403 etc). Now, depending on the status and the length of the response as shown here, IE discards the S3 response and replaces it with a friendly error message. In order to overcome this, you must make sure the response is always > 512 bytes. In this case you cannot guarrantee anything like that cause you don't control the response. S3 does and the typical errors are less than 512 bytes.

Короче:

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

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

3
добавлено
Я действительно ценю, что вы нашли время, чтобы ответить даже после такого долгого времени. Сообщение о сообщениях - отличный трюк, спасибо за обмен. Надеюсь, что многие найдут свое применение :)
добавлено автор Jibi Abraham, источник

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

[edit] для iframes, принятых с помощью errormessage

Сценарий IFRAME

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

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 будет постоянно установлен на ложную проверку, которая проверит, произошла ли ошибка или нет.

1
добавлено
S3 берет на себя фрейм в случае ошибки, к сожалению, я пришел к грустному выводу, что пользователям IE определенно нужно будет согласиться на «Что-то пошло не так», а не то, что точно пошло не так
добавлено автор Jibi Abraham, источник
О, я вижу ... это позор, но это означает, что вы знаете, было ли это принято или нет, просто отправив postMessage в указанный iFrame, если вы получите ответ, все хорошо, если не он был захвачен из-за ошибка...
добавлено автор itsid, источник
@JibiAbraham Я обновил сценарий, чтобы отслеживать, если iframe был захвачен S3
добавлено автор itsid, источник

Summarizing my answer in the comments: IE has CORS support with some restrictions: http://www.html5rocks.com/en/tutorials/cors/

and this implementation of direct upload to S3 looks much simpler than jQuery fileupload and its not in jquery: http://codeartists.com/post/36892733572/how-to-directly-upload-files-to-amazon-s3-from-your

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

1
добавлено
JavaScript Jobs — чат
JavaScript Jobs — чат
8 336 участник(ов)

JavaScript Jobs — чат для поиска работы и людей Правила оформления: https://teletype.in/@telegram-ru/r1WQe5F1m См. также: @mobile_jobs, @devops_jobs, @nodejs_jobs, @react_js, @angular_ru, @js_ru

JavaScript.ru
JavaScript.ru
7 932 участник(ов)

Сообщество сайта JavaScript.ru в Slack.

pro.js
pro.js
4 675 участник(ов)

Про JavaScript и NodeJS Invite: https://t.me/joinchat/Be4rsT5Rsgq30DHutjxXgA Правила: http://telegra.ph/ru-chat-rules-06-19 Вакансии только с ЗП, не чаще раза в неделю.

JavaScript — русскоговорящее сообщество
JavaScript — русскоговорящее сообщество
3 269 участник(ов)

Рекомендуем сразу отключить уведомления Правила: https://rudevs.network/ByaMH6un7 См. также: @js_noobs_ru, @nodejs_ru, @typescript_ru, @react_js, @electron_ru Вакансии и поиск работы: @javascript_jobs

JavaScript Noobs — сообщество новичков
JavaScript Noobs — сообщество новичков
2 484 участник(ов)

Чат для новичков

javascript_ru
javascript_ru
915 участник(ов)

Сообщество любителей самого популярного языка программирования в мире. Чат основан в 2009 году. Логи: https://goo.gl/9EOeM7 Поддержка бота: @chat_linker (ссылка на репу внутри) Вам будут интересны @frontend_ru и @css_ru

jsChat
jsChat
603 участник(ов)

Чат посвященный программированию на языке javaScript Перед отправкой ссылки на Ваш контент посоветуйтесь с админом Все ссылки удаляются ботом автоматически

JavaScript for Zombies Chat
JavaScript for Zombies Chat
492 участник(ов)

Чат про JavaScript для настоящих zombie! Вход строго по приглашениям! Ссылка для строгих приглашений: https://t.me/joinchat/AAMBHz3Uyr0tuZ7VaB029g

All That JS
All That JS
417 участник(ов)

JS на русском