iframe 跨域实践

    前几天遇到个iframe跨域问题,觉得很有意思,现在记录下来,以作存档,也为有类似需要的朋友做一个参考.

    近日,接触到一个网页快照功能,后台如何实现,我们暂且不管,程序给我的要求就是需要当前页面的 body 标签的html内容(去除script标签).按照我的想法,基于jquery,使用ajax的post方式提交本页面的body内容(提交内容之前使用正则替换掉script的内容为空字符),后台返回json格式数据js做相关的处理.

    想到就做,然后我就这么处理了,而且也果然 在本机调试成功了,乐滋乐滋的上了测试地址,然后我发现自己杯具了:这个有跨域需求...

    打个比方:我们当前浏览的页面地址是 http://a.domain.com/a/a.html (也有可能是 http://b.dommain.com/b/b.html 等等任何地址,因为该快照功能被写成一个js文件,需要的页面只需要引入该js文件:snapshot.js 即可实现快照功能)  但是后台程序接受数据的页面地址是 http://f.domain.com/f/ ,而这就存在了一个主域相同,子域不同的问题,存在跨域限制。而我们传送的数据量也许会很大,使用ajax的jsonp方式会自动被转为get方式提交数据,对于我们现在的需求不可行(如果只是传送当前页面的url给后台程序,那就用jsonp方式,方便快捷,而且也可以退坡跨域限制),所以我们只好使用 iframe 来提交数据,具体做法如下:

首先,我们在 f.dommain.com 域下新建一个html文件 snapshot.html(http://f.dommain.com/f/.html),内容如下:

然后我们看 snapshot.js 的内容:

View Code
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>snapshot html page</title>
<script type="text/javascript">
document.domain 
= 'domain.com';// 关键
</script>
</head>
<body>

<form action="http://f.domain.com/f/" method="post">
    <textarea name="html"></textarea>
</form>

</body>
</html>

然后,我们在 snapshot.js 文件里面:

View Code
$(document).ready(function(){
    void function(){
        var $snapshot;

        var _class = {
            init: function(){
                var html = 
                    '<div id="J_SnapshotWrap">'+
                        '<iframe src="http://f.domain.com/f/snapshot.html"></iframe>'+// iframe width: 0;height: 0;border: none;
                        '<button type="button">快照</button>'+
                    '</div>';
                $('body').append(html);
                $snapshot = $('#J_SnapshotWrap');
                $snapshot.find('button').on('click', _class.event.buttonClick:);
            },
            event: {
                buttonClick: function(){
                    var $iframe = $snapshot.find('iframe'), bodyContent = $('body').replace(new RegExp("<script.*<\/script>", 'ig'), '');
                    document.domain = 'dommain.com'; // 关键, 保证当前页与iframe页面的 document.domain 是相等的
                    $iframe.contents().find('body').find('textarea[name=html]').val(bodyContent);
                    $iframe.contents().find('body').find('form').submit();
                    $iframe.attr('data-load', '1');
                    $(this).off('clcik');// 只能点击一次,一个页面只能生成一次快照
                    $(this).on('mouseenter', _class.event.buttonMouseenter);
                    $(this).on('mouseleave', _class.event.buttonMouseleave);
                },
                buttonMouseenter: function(){
                    
                },
                buttonMouseleave: function(){
                    
                }
            }
        };

        _class.init();
    }();
});

这样我们就能跨域提交大容量数据了。

这里主要跨域是设置当前页的 document.domain = 主域,iframe 的document.domain = 主域 这样实现的。

这里还有个事情就是,提交的数据生成了图片,图片地址如何让当前页得到呢?这个又涉及到iframe通信,我的做法比较笨,就是给iframe页面生成一个input隐藏域,把图片地址赋值进去,然后在父页面,鼠标移动到button上时进行判断,判断iframe的data-load是否为‘1’,然后取子页面的隐藏域的值。

 

更进一步:

snapshot.html 页面引入jquery,侦听form submit事件,使用异步方式提交数据,然后在callback函数里面,把返回的图片地址设置给父页面的隐藏域或者其他==

 

下面是一些跨域的资料,列出来作为参考:  

JSONP跨域的原理解析http://www.nowamagic.net/librarys/veda/detail/224

设置 iframe document.domain杂谈 http://lixinlixin2008.iteye.com/blog/515352

iFrame跨域解决办法 http://blog.sina.com.cn/s/blog_63940ce201015w0d.html

 

 

 

posted @ 2012-11-03 16:16  小鱼儿-lovefishs  阅读(366)  评论(1)    收藏  举报