通过I帧的Amazon S3上传(Amazon S3 upload via Iframes)

2019-08-08 16:09发布

叹了口气,我们又回到了这一点。 我可以很轻松地使用在任何足够体面的浏览器CORS直接将文件上传到我的AWS S3桶。 但是,(有人来了),用IE我不得不回落到I帧。 很简单,建立一个隐藏的iframe,创建一个表单,将其目标的iFrame名称/ ID,提交表单。 如果上传成功,则iframe重定向到我指定的网址,我可以访问任何我需要。 但是,如果发生错误,因为现在的iFrame是上AWS域,我不会有机会获得错误的XML内容。 逸岸,我甚至不知道发生了一个错误。

我已经看到了勇敢的人在网上谈论托管HTML文件上,在同一个桶哪些文件被上传,然后用postMessages路由的iframe中的内容,或者诸如此类的东西。

可能有人请向我解释如何实现这个神话的解决方案? 通过Blueimp jQuery的文件上传似乎解决这个问题,但神码是如此jQueryified,我一直没能得到它的要点。

编辑为清楚起见

  1. IE <10不具有的FileReader API。
  2. 因为1,我不能使用XDomainRequest将文件发送到S3
  3. 所以,一个完整的形式S3沿着使用iframe和后
  4. 如果成功的话,AWS重定向到服务器上的页面时,它读取头和
    然后返回可以通过脚本在客户端读取的JSONP风格响应(重定向页面可以
    由我指定)。
  5. 如果出错,所有我现在能做的就是等待超时到期,然后控制台日志
    一个IFRAME ID,和弹出一个警报,使得用户然后可以通过ID查询的iframe中,
    读这该死的XML内容,找出AWS指定的错误,然后重试(我被讽刺..)

Answer 1:

几乎所有你需要知道的jQuery的文件上传插件怎么做的iframe上传一切都在它的iFrame插件运输 (连同配套result.html页)。

作为介绍,您可能需要阅读他们自己的用户指令跨域上传 wiki页面,特别是跨站点IFRAME运输上传部分。 (请注意,根据自己的浏览器支持网页,如上传进度细微不支持IE <10,因此,使用iframe的运输,至少在没有显著的努力,我不会考虑这些可能的。)

(另外,我不认为使用文件上传插件任何S3上传实现访问一个文件上传错误的XML内容)

IFrame的传输插件增加了一个新的Ajax“运输”方法jQuery和不特定的文件上传插件。 您可能需要阅读的文件jQuery.ajaxTransport()明白,jQuery提供了添加新的运输API。


我会试着总结一下的iFrame插件运输是干什么的,以及它如何与上传文件到Amazon S3:

  1. 当一个文件上传被触发, send()函数被调用。 这个功能:

    • 创建隐藏表单元件

    • 创建具有iframe元素src="javascript:false;" ,并结合一个load事件处理程序的IFRAME

    • 追加iframe来隐藏表单,并添加隐藏表单文档。

  2. 在创建iframe和它的“页面”加载,其load的事件处理程序被调用。 处理程序:

    • 清除自己从iframe和结合其他load事件处理程序

    • 配置隐藏的形式:

      • 表单的action将是S3桶网址

      • 表单的target设置为IFRAME,使服务器响应在iframe中加载

      • 其他领域,如AWSAccessKeyId相加。 具体来说, success_action_redirect设置为的URL result.html您的服务器,例如在http://example.org/result.html?%s

        通常情况下, %s令牌应该由服务器端代码上传结果被替换,但S3,这可能是硬编码与你的代码是成功的值,因为亚马逊将重定向到该网址只有在上传成功。

      • 从原来的表单文件输入字段被移动到隐藏的形式,克隆领域留在原来的领域的地方

    • 提交隐藏的表单

    • 移动文件输入字段回原来的形式,取代了克隆领域

  3. 该文件(一个或多个)被上传到S3。 如果成功的话,亚马逊重定向iframe来的success_action_redirect URL。 如果没有成功,亚马逊返回一个错误,其中也加载在iframe。

  4. iframe的load事件处理程序被调用。 处理程序:

    • 试图保存到iframe的参考document对象。 如果文件上传失败,处理程序节省了undefined代替。

    • 调用完成回调返回成功代码和iframe的参考document对象(或undefined

    • 删除隐藏表单(和iframe)

  5. 之前控制返回到您的代码,iframe的document对象被传递到转换器(在底部的iFrame插件运输 ),这取决于你期待什么类型的数据。 该转换器提取从数据document对象,并返回它(或undefined ,如果文件上传失败)到您的回调(或多个)。

  6. 您的回调(S)( success和/或complete传递给jQuery.ajax() )被调用。 一个成功的代码总是由插件返回,所以任何error回调不会被触发。

    如果传递给你的回调(S)的数据是您在包括价值success_action_redirect ,然后将文件上传成功。 如果数据是undefined ,那么该文件上传失败。


更新:如果错误XML页面停留在相同的原点为S3存储,然后从S3斗另一个页面,加载到另一个iframe中,可以访问原来的iframe的内容(因为他们是来自同一个原点)。 你的主要页面可以使用这个第二iFrame沟通postMessage()或easyXDM的FlashTransport,如果你需要支持IE6 / 7)。



Answer 2:

提供准确的反馈到使用不带的FileReader或FORMDATA支持浏览器的用户的这个问题,困扰了我很多的逢。 我花了运动3天尝试拿出一个解决方案,最后用了接近一无所获。

让我们坐下来的事实:

  • 浏览器 :被任何其他浏览器不支持的FileReader IE8 / 9 //薄机会
  • 上传行为 :我们需要的是“阿贾克斯”为UX的原因
  • 列工具 : jQuery的文件上传 *

好了,再有就是比上传使用iframe的文件没有其他办法。 对?

因此,jQuery的使用jQuery的iframe交通运输作为@jeferry_to介绍这么好是适合工作的工具文件上传。

*实际上,工具/插件不会改变的事情..

现在怎么办?

嗯...我们需要访问运输iframe中的S3响应。 但是,我们不能因为它在不同的领域。 因此,我们决定通过使用这种伎俩涉及第二iframe来对付它。

安装:

  • TopFrame,我们的页面(www.myhost.com)
  • IFRAME TransportFrame(s3.amazonaws.com),由插件创建自动 - 包含S3响应
  • IFRAME XDMFrame(s3.amazonaws.com),访问命令时TransportFrame,抓住响应并将其传送到TopFrame

场景:

首先,我们需要修改的jQuery的iframe交通运输,这样它不会自动删除自动生成的表格和传输帧。 我们需要做的,这将在以后使用这项事业#postMessage本质上是异步的,我们不希望通过我们试图访问它的时候消失了的iframe。

  1. 在TopFrame我们将文件上传到S3using jQuery的文件上传。 现在,我们要确保它已被上传否则得到的错误。
  2. TopFrame发送跨域消息使用#postMessage XDMFrame,供给TransportFrame的名称。 此消息实际上是说:“嘿检查IFRAME X”的内容,当你做派他们回来给我。
  3. XDMFrame然后做类似top.frames['iframe X'].document.documentElement访问TransportFrame的TE内容,他们stringifies和并将其发送回TopFrame通过#postMessage。
  4. TopFrame收到消息,显示给用户适当的反馈,并删除,因为我们的jQuery的iframe运输修改的遗留形式和iframe。

好了,一切都应该现在的工作造成一切都是由这本书完成。

Nahh,你不应该甚至不屑。

你看......如果你强制现代浏览器使用的iframe运输代替XHR2上述解决方案将确实像一个魅力的工作。

然而这是没有意义的。 我们希望它在IE8 + 9工作。

嗯......在IE8 / 9有时工作,有时没有。 通常它没有。

为什么? 由于IE浏览器的友好HTTP错误信息。 哦,是的,你看就好了。

在发生错误的情况下,S3具有取决于误差(400,403等)的HTTP错误状态进行响应。 现在,根据状态和如图所示的响应的长度这里 ,IE丢弃S3响应和一个友好的错误消息来替换它。 为了克服这一点,你必须确保反应总是> 512字节。 在这种情况下,因为你不控制响应你不能guarrantee这样的事情。 S3不和典型的误差小于512个字节。

简而言之:

iframe的技巧适用于那些不需要它的浏览器,并且不会对谁做。

遗憾的是,这种情况下,现在关闭了我,我不能想别的。



Answer 3:

总结我的答案的评论:IE浏览器有一些限制CORS支持: http://www.html5rocks.com/en/tutorials/cors/

实施这一项目直接上传到S3的看起来比jQuery的文件上传更简单,它不是在jQuery的: http://codeartists.com/post/36892733572/how-to-directly-upload-files-to-amazon-s3-from-您的

希望这可以帮助!



Answer 4:

AS for the "postMessage" scenario, maybe the iframe should contain a simple javascript

[edit] for iframes taken over by an 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
        }
    }
});

Now parent knows the iFrame perfectly well and can track it's status (depending on if it's answering a simple 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 is not responding with it's "code" iFrameTakenOver will be permanently set to false checking that will verify if an error has occured or not.



文章来源: Amazon S3 upload via Iframes