是否有可能执行异步交叉
有可能的! 参见下文。
首先,让我用这张图解释如何实现异步文件上传 :
抱歉。 我关闭了我的一个域,现在图像已经消失。 这是一个非常好的形象,但。 这是在我发现Stack Overflow允许通过Imgur上传图像之前。
正如你所看到的,诀窍是让HTTP响应加载到隐藏的IFRAME元素中,而不是页面本身。 (这是通过在使用JavaScript提交FORM时设置FORM元素的target
属性来完成的。)
这工作。 但是,我面临的问题是服务器端脚本位于不同的域中 。 FORM-submit是一个跨域HTTP请求。 现在,服务器端脚本启用了CORS,这使得我的网页有权读取从我的页面到该脚本的HTTP请求的响应数据 - 但只有在通过Ajax接收HTTP响应时才有效, ergo,JavaScript。
但是,在这种情况下,响应是针对IFRAME元素的。 一旦XML响应登陆IFRAME,它的URL将成为删除脚本 - 例如http://remote-domain.com/script.pl
。
不幸的是,CORS不包括这种情况(至少我认为) - 我无法读取IFRAME的内容,因为它的URL与页面(不同域)的URL不匹配。 我得到这个错误:
不安全的JavaScript尝试从URL hxxp://my-domain.com/outer.html的框架中访问URL为hxxp://remote-domain.com/script.pl的框架。 域,协议和端口必须匹配。
由于IFRAME的内容是一个XML文档,因此IFRAME内部没有可以使用postMessage
或其他东西的JavaScript代码。
所以我的问题是: 我如何从IFRAME获取XML内容?
正如我上面所说的,我能够直接检索跨域HTTP响应(启用CORS),但似乎我无法在加载到IFRAME中时读取跨域HTTP响应。
就好像这个问题不能解决不了,让我排除这些解决方案 :
easyXDM和需要远程域上的端点的类似技术,
更改XML响应(以包含SCRIPT元素),
服务器端代理 - 我知道我可以在我的域上有一个服务器端脚本,它可以作为代理。
所以,除了这两个解决方案之外,这可以做到吗?
可以办到!!
事实证明,可以伪造一个模拟multipart/form-data
FORM提交的XHR请求(Ajax请求)(在上面的图像中使用它来将文件上传到服务器)。
诀窍是使用FormData
构造函数 - 阅读Mozilla黑客文章以获取更多信息。
这是你如何做到的:
// STEP 1
// retrieve a reference to the file
// <input type="file"> elements have a "files" property
var file = input.files[0];
// STEP 2
// create a FormData instance, and append the file to it
var fd = new FormData();
fd.append('file', file);
// STEP 3
// send the FormData instance with the XHR object
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://remote-domain.com/script.pl', true);
xhr.onreadystatechange = responseHandler;
xhr.send(fd);
上面的方法执行一个异步文件上传,它等同于上图中描述的常规文件上传,并通过提交此表单来实现:
<form action="http://remote-domain.com/script.pl"
enctype="multipart/form-data" method="post">
<input type="file" name="file">
</form>
像一个老板一样 :)
只需使用表单中的数据发送跨域XHR请求,而不是提交表单。 CORS仅适用于前者。
如果您必须以其他方式进行操作,请使用postMessage与框架协商。
由于IFRAME的内容是一个XML文档,因此IFRAME内部没有可以使用postMessage或其他东西的JavaScript代码。
这是如何阻止你? 在HTML或SVG命名空间( <script xmlns="http://www.w3.org/1999/xhtml" type="application/ecmascript" src="..."/>
)下包含脚本元素XML。
我认为这不能用你描述的方式来完成。 通常,如果您有跨域问题,您可以通过JSONp方法解决问题,但只适用于GET请求。 使用HTML5,你可能会发送GET请求的二进制文件,但这仅仅是如此。
一种解决方案是通过在本地Web服务器上代理请求来使远程Web服务在本地可用。 这会给你的本地网络服务器带来额外的负载,所以我可以想象它是不可行的。 如果这些文件很少且很少,那么这样做会很好。
另一种解决方案是在发送文件后开始轮询服务器。 您可以发送令牌并使用常规JSONp轮询服务器的状态。 这样你就不需要从iframe中读取数据。
将整个页面放在远程服务器上运行的iframe中。 这可能只是解决了这个问题,但是如果XML输出是某个过程的最后一步,那么这是非常可行的。
我相信你有一个很好的理由让处理服务器处于不同的域,但如果不是,你不会有这些问题。 也许值得重新考虑?
如果可以的话,返回一个HTML页面而不是XML。
在该页面中,您可以在SCRIPT
标签中使用以下命令: parent.postMessage
如果您必须支持旧浏览器(主要是<IE8),则可以为2Mb以下的消息编写并读取window.name
。
这两种技术都允许您在不同域的帧之间传递字符串数据。
另一种技术是使用setInterval
,它将使用JSONP从父页面反复调用远程域以了解状态。
无论如何,您将需要来自远程域的合作来获取数据。
链接地址: http://www.djcxy.com/p/19591.html