【彻底跨域】异步上传文件并得到返回值

【彻底跨域】异步上传文件并得到返回值javascript

做者:php-note.com  发布于:2015-03-01 10:58  分类:JS/jQuery  浏览(595)php

AJAX能够进行数据的异步请求,但对于文件和跨域问题却一筹莫展。html

Jsonp能够进行跨域数据的异步请求,但一样不能使用于文件。前端

<form>表单能够进行跨域数据和文件的上传,但却会使页面跳转。java

那么如何同时实现“异步”+“跨域”+“文件”+“返回值”这几个特性呢?方法以下:跨域

原理:浏览器

将<form>表单经过一个iframe来submit,也就是将<form>的target属性设置为一个iframe的id,这样<form>的action URL就会在这个iframe中打开,那么服务器的返回数据也就会输出到iframe中了。最后再经过主页面与iframe之间的交互完成对返回数据的读取(这涉及到跨域问题,文章后面将介绍此问题的解决方法)。服务器

基本结构:dom

前端部分(当前域名:www.test.com,与form中的action域名相同)异步

1

<form action="http://www.test.com/io.php" method="POST" enctype="multipart/form-data" target="upload">

2

 

3

        <input type="file" name="upload_file" />

4

 

5

        <input type="submit" value="开始上传" />

6

 

7

</form>

8

 

9

<iframe name="upload" style="display:none"></iframe> // 注意,是name="upload",而不是id="upload"

后台部分

1

<?php

2

 

3

        move_uploaded_file($_FILES['upload_file']['tmp_name'],'upload/' . $_FILES['upload_file']['name']); // 存储上传的文件

4

 

5

        echo 'This data is from server!'; // 返回数据,这行字将输出到iframe的body中

6

 

7

?>

 

优化结构一:

前端部分(当前域名:a.test.com,与form中的action域名不一样)

01

<form action="http://b.test.com/io.php" method="POST" enctype="multipart/form-data" target="upload">

02

 

03

        <input type="file" name="upload_file" />

04

 

05

        <input type="text" name="script" value="http://a.test.com/JS/iframe_control.src.js" style="display:none" /> // 注意这里!

06

 

07

        <input type="submit" value="开始上传" />

08

 

09

</form>

10

 

11

<iframe name="upload" style="display:none"></iframe> // 注意,是name="upload",而不是id="upload"

12

 

13

<script type="text/javascript">

14

 

15

        document.domain="test.com"; // 解决与iframe之间的跨域问题

16

 

17

</script>

后台部分

01

<?php

02

 

03

        move_uploaded_file($_FILES['upload_file']['tmp_name'],'upload/' . $_FILES['upload_file']['name']); // 存储上传的文件

04

 

05

        $html = '<html><head>'

06

 

07

                    . '<script src="' . $_POST['script'] .'" type="text/javascript"></script>' // 注意这里!

08

 

09

                    . '</head><body>'

10

 

11

                    . 'This data is from server!' // 返回数据,这行字将输出到iframe的body中

12

 

13

                    . '</body></html>';

14

 

15

        echo $html;

16

 

17

?>

经过上面的优化,iframe从服务器接收到的内容中就多了一条<script>标签,这个标签的src是由<form>表单提交的,也就是说这个js文件可

以放在任何域名下,而且经过修改该js的内容来制定这个iframe的功能。好比,在其中调用document.domain="test.com"后,即可以与主页面

互相通讯与控制了(主页面中也调用了document.domain="test.com",所以跨域限制被消除了)。

 

优化结构二:

前端部分(当前域名:www.a.com,与form中的action域名不一样)

01

<form action="http://www.b.com/io.php" method="POST" enctype="multipart/form-data" target="upload">

02

 

03

        <input type="file" name="upload_file" />

04

 

05

        <input type="text" name="tmpurl" value="http://www.a.com/tmp.html" style="display:none" /> //注意这里!

06

 

07

        <input type="submit" value="开始上传" />

08

 

09

</form>

10

 

11

<iframe name="upload" style="display:none"></iframe> //注意,是name="upload",而不是id="upload"

此次咱们没有看到<script>标签,由于再也不须要了,请继续看后台代码:

后台部分

1

<?php

2

 

3

        move_uploaded_file($_FILES['upload_file']['tmp_name'],'upload/' . $_FILES['upload_file']['name']); // 存储上传的文件

4

 

5

        $data = 'This data is from server!' // 返回数据,这行字将经过URL返回给浏览器

6

 

7

        header('Location:' . $_POST['tmpurl'] . '?data=' . $_data); // 上传完成后使iframe直接跳转至$_POST['tmpurl']

8

 

9

?>

与优化结构一不一样的是,结构二中再也不使用“指定document.domain为一级域名”来解除跨域限制,也不经过iframe的document内容来获得返

回数据,而是经过使iframe直接跳转至当前域名(经过$_POST['tmpurl']指定)来完全取消跨域限制而且经过url的search部分传递返回数据。

 

两种结构的对比:

跨域:优化结构一只可解决一级域名相同的状况下的跨域状况,而优化结构二可解决任何跨域,好比百度与google之间。

数据:优化结构一的返回数据无大小限制,而优化结构二的返回数据必须小于2K(由于数据是经过RUL传输的)。

相关文章
相关标签/搜索