首页 > 其他分享 >js:浏览器跨域ajax变通实现 -- flash + js + crossdomain.xml

js:浏览器跨域ajax变通实现 -- flash + js + crossdomain.xml

时间:2023-04-10 16:08:00浏览次数:38  
标签:xml function 跨域 ops url flash js window fajax


使用此方式能很好解决这个问题,因为考虑了php中转形式的双倍时间和莫须有的访问,不是很愿意用,除非不得已,现在找到flash的实现方法,对于能自按的服务器来说这是不错的解决方案,只需要担心的是有人不愿意安装flash控件,且能解决script方式 的不能post不足,除非浏览器已经统一支持跨域header标准,否则,这个是不错的解决.

 

-----------------fajax.swf制作与as--------------
/*
 * 创建swf步骤:
 * 打开flash,创建一个项目,把本as文件加入
 * 创建一个fla空白文件,设置fla文档属性的文档类为本公类名 fajax,保存fla,并在项目中加入fla
 * 发布项目后使用生成的swf即可
 * js调用as必须所有的参数都有值,否则会出错
 */
package {    
  import flash.display.Sprite;
  public class fajax extends Sprite {
    import flash.external.ExternalInterface;
    import flash.system.Security;
    import flash.system.System;
    Security.allowDomain("*");

    private var objects:Object;
    
    public function fajax():void {
        super();
        System.useCodePage = false;//使用utf8编码,否则使用用户系统编码
        ExternalInterface.addCallback("create", create); //注册swf中方法可以让js调用
        ExternalInterface.addCallback("addHeader", addHeader); 
        ExternalInterface.addCallback("send", send);  
        ExternalInterface.addCallback("finishing", finishing); 
        ExternalInterface.addCallback("existId", existId); 
        objects = new Object();
    }

    public function create(id:Number, method:String, url:String):void {
        if (!url) return;
        var requester:HttpRequester = new HttpRequester(this, id, method, url);
        objects[id] = requester;
    }

    public function addHeader(id:String, name:String, value:String):void {
        objects[id].addHeader(name, value);
    }
    public function send(id:String, content:String):void {
        objects[id].send(content);
    }

    public function handler(id:String, data:String, ok:Number):void {
        ExternalInterface.call( stage.loaderInfo.parameters.jsName + ".swfCall(" + id + ", unescape('" + escape(data) + "'), " + ok + ") && 0 && isNaN");
        finishing(id);
    }    
    
    public function finishing(id:String):void {
        objects[id] = null;//清除flash对象
    }
    
    public function existId(id:Number):Number {//检测对象是否存在
        return objects[id] ? 1 : 0;
    }
  }
}
/*
 * 请求类,不能放到包中,在同包中不用包含
 */
 dynamic class HttpRequester{
    import flash.errors.IOError;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLRequestHeader;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;

    private var id:Number;
    private var request:URLRequest;
    private var parent:Object;
    public function HttpRequester(parent_:Object,id_:Number, 
        method:String, url:String):void {
        id = id_;
        parent = parent_;
        request = new URLRequest(url);
        request.method = method.toUpperCase()=='POST' ? URLRequestMethod.POST : URLRequestMethod.GET;
    }

    public function addHeader(name:String, value:String):void {
        var header:URLRequestHeader = new URLRequestHeader(name, value);
        if (!request.requestHeaders)
          request.requestHeaders = new Array(header);
        else
          request.requestHeaders.push(header);
    }

    public function send(data:String):void {
        if (request.method == 'POST')
          request.data = data;//必须是post,否则必须附加到url上
        var loader:URLLoader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, handler);
        loader.addEventListener(IOErrorEvent.IO_ERROR, handler);
        loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handler);
        loader.load(request);
    }

    public function handler(e:Event):void {
      var loader:URLLoader = URLLoader(e.target);
      loader.removeEventListener(Event.COMPLETE, handler);
      loader.removeEventListener(IOErrorEvent.IO_ERROR, handler);
      var integration:String;
      if ( e.type != IOErrorEvent.IO_ERROR && e.type != SecurityErrorEvent.SECURITY_ERROR ) {
        parent.handler(id, loader.data, 1); // fix status
      } else {
        parent.handler(id, loader.data, 0); // error TODO
      }
    }
} 
------------------fajax.js 代码-----------
 
/*
ajax(ops) = {
    post:1 //默认post
    ,url:''
    ,ok:callback//成功执行 (data) 参数全部是字符
    ,fail: null//失败执行 (data)
    ,out:null //超时执行 ()
    ,header:{} //头
    ,wait:60 //超时秒,默认60
    ,data:{        //数据        
        aid:CHRD.getObj('aid').value
        ,comment:CHRD.getObj('commentText').value
        ,title:CHRD.getObj('aTitle').innerHTML
        ,desc:CHRD.getObj('aDesc').innerHTML
        ,verify: CHRD.getObj('commentVerify').value
        ,sendBlog:CHRD.getObj('sendBlog').checked ? 1 : 0
        ,url:location.href
    }
}

注意:被请求服务器必须在根域存在crossdomain.xml文件,有关此文件语法请搜索
必须在页面未加载完成前加载本js,因为考虑到有时必须在加载未完成前可以使用
*/
(function(fajax, dir) {
    if (window[fajax]) return alert(fajax + '重复加载/命名冲突');
    //加载swf
    var ie = 'function' == typeof ActiveXObject;
    var idPre = 'swfAjaxQidizi';
    //不允许隐藏swf,在ie下,
    //发现一个问题就是,动态加载css文件时,本swf会被重载,可以使用定时询问swf本queuei是否存在,不存在时,重新请求
    document.write('<object id="' + idPre + fajax + '" '
                + (
                   ie ? ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" '
                       :
                        ' type="application/x-shockwave-flash" data="' + dir + 'fajax.swf?jsName=' + fajax+ '" '                 
                )
                + ' style="width:1px;height:1px;position: absolute;top:0px;left:0px;display:block;" >'
                + '<param name="movie" value="' + dir + 'fajax.swf?jsName=' + fajax+ '" />'
                + '<param name="allowscriptaccess" value="always">'
                + '</object>');    
    var obj2url = function(obj) {
        if (!obj || (obj.constructor != {}.constructor) ) return '';
        var a = [];      
        for (var p in obj) a.push('&' + p + '=' + encodeURIComponent(obj[p]));        
        return a.join('');
    }
    window[fajax] = function (ops) {
        if (!ops) return alert('必须提交参数');
        if (!ops.url || !/^https?\:\/\/[^\/]+/i.test(ops.url)) return alert('必须是http[s]协议的url');                
        ops.url = ops.url.replace(/#.*$/, '');//移除苗点
        
        if (
            (!window[fajax].swfer && !(window[fajax].swfer = document.getElementById(idPre + fajax))) //无swf对象,尝试获取
            || !window[fajax].swfer.create //有swf对象,但是无法正常解析swf
        ) {            
            if ('complete' != document.readyState) {//页面未载入完成,延后再试
                setTimeout(function(){window[fajax](ops);}, 100);                
                return;
            } else {//载入完成了
                return !confirm(
                        ops.url + ' 的请求无法处理\n'
                        + '\n页面未能检测到fajax.swf:用来不必刷新页面就能提交/获取数据.'
                        + '\n1. 可能是你的浏览器禁用/未安装flash控件:请启用/安装;'
                        + '\n2. 可能是开启了过滤浮动flash功能:请忽略本安全flash;'
                        + '\n3. flash控件被破坏:请检查浏览器设置或是重新安装flash控件;'
                        + '\n4. flash版本低于flash 9.0:请安装最新flash版本;'
                        + '\n\n点击 [取消] 按钮,立刻跳转到下面flash官方网址,然后按照页面指引进行flash控件的安装\n\n'
                        + 'http://www.adobe.com/go/getflashplayer\n'
                        + '\n点击 [确定] 按钮,忽视本提示,然后自己解决本问题'
                        + '\n\n解决问题后刷新页面即可正常使用\n'
                        + '\n祝您使用愉快!'
                        + '如果需要任何帮助,请联系我们:论坛求助或是来信.'
                        ) && (location.href = 'http://www.adobe.com/go/getflashplayer');
            }
        }
        
        if (!/^https?\:\/\/[^\/\?]+\//i.test(ops.url)) {//域名后面必须有/
            ops.url = ops.url.replace(/^https?\:\/\/[^\/\?]+/i
                ,function($0) {
                    return $0 + '/';
                }
            );//保证/号
        }
        
        var queueI = window[fajax].queue.i++;
        window[fajax].queue[queueI] = {//记录回调
            ok:typeof ops.ok == 'function' ? ops.ok : function(){}
            , fail:typeof ops.fail == 'function' ? ops.fail : function(){}
        };
        var vars = obj2url(ops.data);
        window[fajax].swfer.create(queueI, ops.post ? 'POST' : 'GET', ops.post ? ops.url : (ops.url.indexOf('?') > -1 ? ops.url : ops.url + '?') + vars);
        for (var h in ops.header)  window[fajax].swfer.addHeader(queueI, h, ops.header[h]);//加头
        window[fajax].swfer.send(queueI, vars);//发送,必须传递所有的值  
        var wait = ops.wait > 0 ? ops.wait : 60;      
        //设定定时,如果超时不返回清除对象
        window[fajax].queue[queueI].timer = setInterval(//一秒检测一次
            function() {
                if (!window[fajax].swfer.existId(queueI)) {//可能是被重载了,重新请求
                    clearInterval(window[fajax].queue[queueI].timer);//清除超时检测
                    window[fajax].swfer.finishing(queueI);//假设
                    window[fajax].queue[queueI] = null;
                    window[fajax](ops);//重新请求
                    return;
                }
                
                if (--wait < 0) {
                    clearInterval(window[fajax].queue[queueI].timer);//清除超时检测
                    window[fajax].swfer.finishing(queueI);
                    (typeof ops.out == 'function') && ops.out.call();//超时的完成
                    window[fajax].queue[queueI] = null;
                }
            }
            ,1000
        );
    }
    window[fajax].queue = {i:0};//队列
    window[fajax].swfCall = function(i, data, ok) {//成功返回
        clearInterval(window[fajax].queue[i].timer);//清除超时检测
        ok ? window[fajax].queue[i].ok.call(window, data)//ok的完成
           : window[fajax].queue[i].fail.call(window, data);//失败        
        window[fajax].queue[i] = null;
        window[fajax].swfer.finishing(i);
    }           
})('swfAjax', 'http://cms.chinahrd.net/statics/js/chrd/fajax/'); 
---------使用方式-----------
<script src="{JS_PATH}chrd/fajax/fajax.js"></script>
 
swfAjax(
  {
      post:1 //默认post
      ,url:'http://community.chinahrd.net/chrd/?m=comment&c=newArticle'
      ,ok:callback//成功执行
      ,fail:callback //失败执行
      ,out:callback //失败执行
      ,header:{} //头
      ,data:{        //数据        
          aid:CHRD.getObj('aid').value
          ,comment:CHRD.getObj('commentText').value
          ,title:CHRD.getObj('aTitle').innerHTML
          ,desc:CHRD.getObj('aDesc').innerHTML
          ,verify: CHRD.getObj('commentVerify').value
          ,sendBlog:CHRD.getObj('sendBlog').checked ? 1 : 0
          ,url:location.href
      }
  }
);     
function callback(data) {
    alert(data);
}

直接使用alert或prompt会出现没提示情况,但是请求返回已完成

 

无时间检测flash的call js的形态,为了方便直接使用escape后再un,可能在大量数据上性能不好.

已经实现了异步功能,经测试,内存回收还是有问题.有些形态应该更改成局部变量;

 

js:浏览器跨域ajax变通实现 -- flash + js + crossdomain.xml_ajax

标签:xml,function,跨域,ops,url,flash,js,window,fajax
From: https://blog.51cto.com/u_252283/6181039

相关文章