是否可以执行异步跨域文件上传? [英] Is it possible to perform an asynchronous cross-domain file-upload?

查看:120
本文介绍了是否可以执行异步跨域文件上传?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是可能的!请先阅读下面的内容。






首先,让我们使用此图说明异步文件上传可以实现:






对不起。我关闭了我的一个域,现在图像已经不见了。这是一个非常好的形象。这是在我发现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的内容,因为其网址与网页(不同的域)的网址不匹配。我收到此错误:


不安全的JavaScript尝试使用URL访问框架
hxxp://remote-domain.com/script .pl从框架与URL
hxxp://my-domain.com/outer.html。域,协议和端口必须
匹配。


由于IFRAME的内容是XML文档,因此我的问题是: 如何从IFRAME获取XML内容?



如上所述,我可以直接检索跨域HTTP响应),但似乎一旦它们加载到IFRAME中,我就无法读取跨域HTTP响应。



如果这个问题不能解决,让我排除这些解决方案


  1. easyXDM和类似的技术,远程域,


  2. 更改XML响应(包括SCRIPT元素),


  3. 服务器端代理 - 我理解我可以在我的域上有一个可以作为代理的服务器端脚本。


那么,除了这两个解决方案,可以这样做吗?






/ h1>

事实证明,可以伪造一个模仿 multipart / form-data FORM提交(在上面的图片中用于将文件上传到服务器)。



窍门是使用 FormData 构造函数 - 请阅读此Mozilla Hacks article 了解更多信息。



这是您的操作方式:

  // STEP 1 
//检索对文件的引用
//< input type =file>元素有一个files属性
var file = input.files [0];

//步骤2
//创建一个FormData实例,并将文件附加到它
var fd = new FormData();
fd.append('file',file);

// STEP 3
//使用XHR对象发送FormData实例
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-datamethod =post>
< input type =filename =file>
< / form>



像Boss:)


解决方案

只需发送带有表单数据的跨域XHR请求,而不是提交表单。 CORS只适用于前者。



如果你必须这样做,使用postMessage协商框架。


由于IFRAME的内容是一个XML文档,IFRAME中没有可以使用postMessage或其他东西的JavaScript代码。




如何阻止你?在HTML或SVG命名空间(< script xmlns =http://www.w3.org/1999/xhtmltype =application / ecmascriptsrc =...下包含脚本元素/> )。


It is possible! Read below.


First of all, let me use this diagram to explain how asynchronous file uploads can be achieved:


Sorry. I've shut down one of my domains, and the image is gone now. It was a really nice image though. This was before I found out that Stack Overflow enables uploading images via Imgur.


As you can see, the trick is to let the HTTP-response load into a hidden IFRAME element instead of the page itself. (This is done by setting the target property of the FORM element when submitting the FORM with JavaScript.)

This works. However, the problem I'm facing is that the server-side script is on a different domain. The FORM-submit is a cross-domain HTTP-request. Now, the server-side script has CORS enabled which gives my web-page the rights to read the response-data of HTTP-requests made from my page to that script - but that works only if I receive the HTTP-response via Ajax, ergo, JavaScript.

However, int this case, the response is directed towards the IFRAME element. And once the XML response lands into the IFRAME, its URL will be the remove script - e.g. http://remote-domain.com/script.pl.

Unfortunately, CORS does not cover this case (at least I think) - I am not able to read the contents of the IFRAME since its URL doesn't match the URL of the page (different domain). I get this error:

Unsafe JavaScript attempt to access frame with URL hxxp://remote-domain.com/script.pl from frame with URL hxxp://my-domain.com/outer.html. Domains, protocols and ports must match.

And since the contents of the IFRAME is an XML document, there is no JavaScript code inside the IFRAME which could make use of postMessage or something.

So my question is: How can I get the XML contents from the IFRAME?

As I said above, I am able to retrieve cross-domain HTTP-responses directly (CORS enabled), but it seems that I am not able to read cross-domain HTTP-responses once they load into an IFRAME.

And as if this question is not unsolvable enough, let me exclude these solutions:

  1. easyXDM and similar techniques which require an end-point on the remote domain,

  2. altering the XML response (to include a SCRIPT element),

  3. server-side proxy - I understand that I could have a server-side script on my domain which could serve as a proxy.

So, apart from those two solutions, can this be done?


It can be done!!

It turns out that it is possible to forge a XHR-request (Ajax-request) which imitates a multipart/form-data FORM submit (which is used in the image above to upload the file to the server).

The trick is to use FormData constructor - read this Mozilla Hacks article for more information.

This is how you do it:

// 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);

The above method executes an asynchronous file-uplaod, which is equivalent to the regular file-upload described in the image above and achieved by submitting this form:

<form action="http://remote-domain.com/script.pl" 
        enctype="multipart/form-data" method="post">
    <input type="file" name="file">
</form>

Like a Boss :)

解决方案

Just send a cross-domain XHR request with the data from the form instead of submitting the form. CORS is only for the former.

If you must do it the other way, negotiate with the frame using postMessage.

And since the contents of the IFRAME is an XML document, there is no JavaScript code inside the IFRAME which could make use of postMessage or something.

How does that stop you? Include a script element under the HTML or SVG namespace (<script xmlns="http://www.w3.org/1999/xhtml" type="application/ecmascript" src="..."/>) anywhere in the XML.

这篇关于是否可以执行异步跨域文件上传?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆