Amazon S3 upload via Iframes

后端 未结 4 1809
北荒
北荒 2021-02-01 05:16

Sigh, we\'re back to this. I can easily enough use CORS on any decent enough browser to directly upload files to my AWS S3 bucket. But (it was coming), with IE I have to fall ba

4条回答
  •  孤街浪徒
    2021-02-01 06:09

    This problem, of providing accurate feedback to users using browsers with no FileReader or FormData support has troubled me a lot as wel. I spent a whole 3 days trying to come up with a solution and finally came up with something close to nothing.

    Lets get down to the facts:

    • 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*

    Ok, then there is no other way of uploading the file than using an iframe. Right?

    So, jQuery File Upload using jQuery Iframe Transport as @jeferry_to describes so well is the tool for the job.

    *Actually the tool/plugin doesn't change a thing..

    What now?

    Well... we need to access the S3 response inside the transport iframe. But we can't because its on a different domain. So we decide to deal with it by using this trick involving a second iframe.

    The setup:

    • TopFrame, our page (www.myhost.com)
    • iframe TransportFrame (s3.amazonaws.com), auto created by the plugin - contains the S3 response
    • iframe XDMFrame (s3.amazonaws.com), accesses the TransportFrame when ordered, grabs the response and delivers it to TopFrame

    The scenario:

    First of all we need to modify jQuery Iframe Transport so that it does not auto remove the auto-generated form and transport frame. We need to do this cause #postMessage which will use later is asynchronous by nature and we don't want the iframe gone by the time we try to access it.

    1. on TopFrame we upload a file to S3using jQuery File Upload. We now want to make sure it has been uploaded and get the error otherwise.
    2. TopFrame sends a cross domain message to XDMFrame using #postMessage, supplying the name of the TransportFrame. This message actually says: 'Hey check the contents of iframe X' and when you do send em back to me.
    3. XDMFrame then does something like top.frames['iframe X'].document.documentElement to access te contents of the TransportFrame, stringifies them and sends them back to TopFrame through #postMessage.
    4. TopFrame receives the message, shows the proper feedback to the user and removes the form and iframe left over because of our jQuery Iframe Transport modification.

    Ok, everything should work now cause everything is done by the book.

    Nahh, you should not even bother.

    You see... if you force a modern browser to use the iframe transport instead of the XHR2 the above solution will indeed work like a charm.

    However that's pointless. We want it to work in IE8 + 9.

    Well... in IE8/9 it sometimes work, it sometimes doesn't. Usually it doesn't.

    Why? Because of the IE's friendly HTTP error messages. Oh yes you read just fine.

    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.

    In short:

    The iframe trick works on those browsers that do not need it, and doesn't on those who do.

    Unfortunately, I can't think of anything else so that case is closed for me now.

提交回复
热议问题