叹了口气,我们又回到了这一点。 我可以很轻松地使用在任何足够体面的浏览器CORS直接将文件上传到我的AWS S3桶。 但是,(有人来了),用IE我不得不回落到I帧。 很简单,建立一个隐藏的iframe,创建一个表单,将其目标的iFrame名称/ ID,提交表单。 如果上传成功,则iframe重定向到我指定的网址,我可以访问任何我需要。 但是,如果发生错误,因为现在的iFrame是上AWS域,我不会有机会获得错误的XML内容。 逸岸,我甚至不知道发生了一个错误。
我已经看到了勇敢的人在网上谈论托管HTML文件上,在同一个桶哪些文件被上传,然后用postMessages路由的iframe中的内容,或者诸如此类的东西。
可能有人请向我解释如何实现这个神话的解决方案? 通过Blueimp jQuery的文件上传似乎解决这个问题,但神码是如此jQueryified,我一直没能得到它的要点。
编辑为清楚起见
- IE <10不具有的FileReader API。
- 因为1,我不能使用XDomainRequest将文件发送到S3
- 所以,一个完整的形式S3沿着使用iframe和后
- 如果成功的话,AWS重定向到服务器上的页面时,它读取头和
然后返回可以通过脚本在客户端读取的JSONP风格响应(重定向页面可以
由我指定)。 - 如果出错,所有我现在能做的就是等待超时到期,然后控制台日志
一个IFRAME ID,和弹出一个警报,使得用户然后可以通过ID查询的iframe中,
读这该死的XML内容,找出AWS指定的错误,然后重试(我被讽刺..)
几乎所有你需要知道的jQuery的文件上传插件怎么做的iframe上传一切都在它的iFrame插件运输 (连同配套result.html页)。
作为介绍,您可能需要阅读他们自己的用户指令跨域上传 wiki页面,特别是跨站点IFRAME运输上传部分。 (请注意,根据自己的浏览器支持网页,如上传进度细微不支持IE <10,因此,使用iframe的运输,至少在没有显著的努力,我不会考虑这些可能的。)
(另外,我不认为使用文件上传插件任何S3上传实现访问一个文件上传错误的XML内容)
IFrame的传输插件增加了一个新的Ajax“运输”方法jQuery和不特定的文件上传插件。 您可能需要阅读的文件jQuery.ajaxTransport()明白,jQuery提供了添加新的运输API。
我会试着总结一下的iFrame插件运输是干什么的,以及它如何与上传文件到Amazon S3:
当一个文件上传被触发, send()
函数被调用。 这个功能:
在创建iframe和它的“页面”加载,其load
的事件处理程序被调用。 处理程序:
该文件(一个或多个)被上传到S3。 如果成功的话,亚马逊重定向iframe来的success_action_redirect
URL。 如果没有成功,亚马逊返回一个错误,其中也加载在iframe。
iframe的load
事件处理程序被调用。 处理程序:
之前控制返回到您的代码,iframe的document
对象被传递到转换器(在底部的iFrame插件运输 ),这取决于你期待什么类型的数据。 该转换器提取从数据document
对象,并返回它(或undefined
,如果文件上传失败)到您的回调(或多个)。
您的回调(S)( success
和/或complete
传递给jQuery.ajax() )被调用。 一个成功的代码总是由插件返回,所以任何error
回调不会被触发。
如果传递给你的回调(S)的数据是您在包括价值success_action_redirect
,然后将文件上传成功。 如果数据是undefined
,那么该文件上传失败。
更新:如果错误XML页面停留在相同的原点为S3存储,然后从S3斗另一个页面,加载到另一个iframe中,可以访问原来的iframe的内容(因为他们是来自同一个原点)。 你的主要页面可以使用这个第二iFrame沟通postMessage()
或easyXDM的FlashTransport,如果你需要支持IE6 / 7)。
提供准确的反馈到使用不带的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。
- 在TopFrame我们将文件上传到S3using jQuery的文件上传。 现在,我们要确保它已被上传否则得到的错误。
- TopFrame发送跨域消息使用#postMessage XDMFrame,供给TransportFrame的名称。 此消息实际上是说:“嘿检查IFRAME X”的内容,当你做派他们回来给我。
- XDMFrame然后做类似
top.frames['iframe X'].document.documentElement
访问TransportFrame的TE内容,他们stringifies和并将其发送回TopFrame通过#postMessage。 - TopFrame收到消息,显示给用户适当的反馈,并删除,因为我们的jQuery的iframe运输修改的遗留形式和iframe。
好了,一切都应该现在的工作造成一切都是由这本书完成。
Nahh,你不应该甚至不屑。
你看......如果你强制现代浏览器使用的iframe运输代替XHR2上述解决方案将确实像一个魅力的工作。
然而这是没有意义的。 我们希望它在IE8 + 9工作。
嗯......在IE8 / 9有时工作,有时没有。 通常它没有。
为什么? 由于IE浏览器的友好HTTP错误信息。 哦,是的,你看就好了。
在发生错误的情况下,S3具有取决于误差(400,403等)的HTTP错误状态进行响应。 现在,根据状态和如图所示的响应的长度这里 ,IE丢弃S3响应和一个友好的错误消息来替换它。 为了克服这一点,你必须确保反应总是> 512字节。 在这种情况下,因为你不控制响应你不能guarrantee这样的事情。 S3不和典型的误差小于512个字节。
简而言之:
iframe的技巧适用于那些不需要它的浏览器,并且不会对谁做。
遗憾的是,这种情况下,现在关闭了我,我不能想别的。
总结我的答案的评论: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-您的
希望这可以帮助!
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.