Form Post数据 + Iframe跨域回调 全公开

Script标签跨域简单易懂,对于没有Post要求的数据请求,还是使用Script标签+Jsonp比较靠谱

代码:

 a.scriptGet = function (url, callback,onerror) {
        var stag = document.createElement("script");
        stag.type = "text/javascript";
        stag.src = url + "&t=" + (new Date()).getTime();
        stag.iSnoBack = true;
        stag.onload = stag.onreadystatechange = function () {
            stag.iSnoBack = false;
            if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') {
                document.body.removeChild(stag);
                if (callback)
                    callback();
            }
        }
        document.body.appendChild(stag);
        setTimeout(function () { 
            if(stag.iSnoBack)
            {
                document.body.removeChild(stag);
                if (onerror)
                {
                    onerror();
                }
                else
                    alert("请求的跨域资源:"+url+"没有在10秒内返回,可能已经发生错误,请检查或刷新页面");
            }
        },10000);
    };

Script跨域要求服务器端返回的 ContentType =  text/javascript

内容文件形如:

     calbackName({"success":true,"errorinfo":"all OK"});

     相当于在HTML的script标签内直接调用某个函数。跨域的Cookie支持没有理论上的可能性,数据安全性都需要自己定协议才能支持。




对于需要提交数据,特别是需要跨域Post文件的系统,Get标签就有各种限制了,这时候需要使用Form进行跨域,代码:

a.DoCallBack = function (fc) {
        try {
            eval(fc);
        }
        catch (e) {
            alert("跨域数据传递返回数据错误:" + e.message);
        }
    }
var seriNo = 1;//跨域操作流水号

    a.CPBack = function (frameID, data) {
        var backFrm = document.getElementById(frameID);
        if (!backFrm)
            return;
        var t = getHiddenDivDirect.Target;
        t.removeChild(backFrm);

        if (!backFrm.CPCallBackk)
            return;

        backFrm.CPCallBackk(data);
    }

a.FormPost = function (mainCMD, subCmd, content, callBackName) {
        //2层Frame跨域,无File上传
        //如果需要上传File,那么需要在HTML的From中完成
        var frm = getHiddenDiv(frm);
        if (frm == null)
        {
            alert("跨域等待数操作最大值");
            return;
        }
        frm.CPCallBackk = callBackName;


        var mainCC = {};
        mainCC.CallBack = frm.id;
        mainCC.CrossPageUrl = CPConfig.Local.CPFile;
        mainCC.Command = mainCMD;
        var mainCCStr = JSON.stringify(mainCC);


        frm.contentWindow.document.open();
        var wDoc = frm.contentWindow.document;
        wDoc.write("<html><head><title></title></head>");
        wDoc.write("<body><form id='autoForm' enctype='multipart/form-data' action='");
        wDoc.write(CPConfig.Server.Using);
        wDoc.write("' target='hiddenFrm' method='post'><textarea name=\"c\">");
        wDoc.write(content);
        wDoc.write("</textarea><textarea name=\"a\">");
        wDoc.write(mainCCStr);
        wDoc.write("</textarea><textarea name=\"b\">");
        wDoc.write(subCmd);
        wDoc.write("</textarea></form><iframe name=\"hiddenFrm\"/></body></html>");
        wDoc.close();
        var formT = wDoc.getElementById("autoForm");
        formT.submit();


    }


    function getHiddenDiv() {
        var noSeriIO = seriNo++;
        var frm = document.createElement("iframe");
        frm.id = "ghChainHiddenPost" + noSeriIO;


        var t = document.createElement("div");
        t.id = "gfChainHiddenContainer";
        t.style.cssText = "display:none;position:absolute;width:0px;height:0px;";
        if (document.body == null)
            alert("不能在Head的JS中Post数据,请移动到HTML末尾处");
        else
            document.body.appendChild(t);
        getHiddenDivDirect.Target = t;
        getHiddenDiv = getHiddenDivDirect;


        t.appendChild(iframe);
        return iframe;
    }
    function getHiddenDivDirect() {
        var t = getHiddenDivDirect.Target;
        if (t.childNodes.length > 20) {//======================最大跨域提交等待数;========================
            return null;
        }


        var noSeriIO = seriNo++;
        var frm = document.createElement("iframe");
        frm.id = "ghChainHiddenPost" + noSeriIO;
        t.appendChild(iframe);
    }



这里的函数是提交大的数据对象。 如果需要提交文件,那么需要手工编辑iframe的内容,然后显示出来。 

甚至,这里可以去掉iframe,将form放在任意HTML文件中,放在邮件中也没有问题。


其本质就是一个跨域的form提交操作,可以JS自动生成,也可以嵌入在HTML页面中,显示给用户让编辑修改内容后再提交到服务器。

数据提交到服务器端后,需要几个条件,才能通JS通知到原来的域:

   1:服务器端返回一个特定的HTML页面,通过HASH值传递数据对象

   2:在原始域,需要有一个特殊的数据接收文件来接收数据,并完成回掉

服务器端返回的HTML内容:CPCPFather.html

<html><head><title>跨域中间页</title></head><body>本页是Form Post后返回数据页,应将form的target指向一个隐藏的iframe,不应显示出来。
<iframe src="CPCP.html#callback({\"success\":true,\"errorinfo\":\"all ok\"})"></iframe>
</body></html>

其中的callback({\"success\":true,\"errorinfo\":\"all ok\"})是重点,上述实例中没有对数据进行escap操作,实际应用中,必须进行escape否则会有意外发生.


iframe和原始域虽然可以互相访问,但因为在不同的window对象下,函数可能无法找到。实际代码中可以直接把函数关联到window.top对象上,然后直接回掉window.top上的函数。上述代码的a对象,就设置了:

window.top.CPJS = a;



在原始域中CPCP.html文件内容

<html><head><title>跨域回调页</title></head>
<body>
    本页面应该隐藏在iframe中。无可显示内容
<script type="text/javascript">
try{
var hStr = window.location.hash;
if (hStr[0] == '#')
{
    hStr = hStr.substr(1, hStr.length - 1);
}
hStr = unescape(hStr);
window.top.CPJS.DoCallBack(hStr);
}
catch (e) {
    alert("跨域回掉错误:"+e.message+"\r\n数据内容:"+hStr);
}
</script></body></html>

该文件是静态文件,建议放在根目录下。





代码已经通过测试,iframe跨域的响应非常及时。

整个过程没有使用settime来进行数据检测,已使用的两个settime函数是为了错误检测,可以去掉。

数据返回域的Cookie操作没有测试,估计在CPCPFather.html文件中,对Cookie操作不会有问题,有兴趣的同学可以帮忙测试一下。


OK.Thansk.




 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值