[文章+部分代码 作者:张宴 本文版本:v1.0 最后修改:2009.03.09 转载请注明原文链接:http://blog.zyan.cc/ajaxcdr/]

  最近的一个项目中,需要通过 JavaScript 提交表单数据到另一个域名下的PHP接口(因为数据较大,需要HTTP POST方式提交),并获取PHP接口的返回值,在页面无刷新、无跳转的情况下,更新div标签内的内容。

  浏览器出于安全考虑,是不允许JavaScript代码进行跨域操作。JavaScript 和 AJAX 跨域访问分为两大类,一是本域和子域的交互,二是本域和其他域的交互。

  一、本域和子域的交互:www.zyan.cc 和 blog.zyan.cc
  二、本域和其他域的交互:blog.zyan.cc 和 api.bz

  本域和子域的交互,可以通过iframe设置两个域名document.domain = "zyan.cc",实现统一zyan.cc域下的跨域访问。

  本域和其他域的交互,可以通过iframe、代理、JS创建动态脚本等几种方法来实现,这里有篇文章对几种方法作了简要的介绍

  iframe、JS创建动态脚本这两种方法,需要开发者能控制两个域,两端都要编写相应的代码,非常麻烦。在本域服务器上用PHP写个代理中转程序,让本域PHP程序去读取远程其他域的数据再返回给自己,是常用的方法。但是,在本域“前端是CDN或Squid缓存服务器,后端才是PHP应用程序服务器”的系统架构下,穿透CDN或Squid去访问不能被缓存的PHP代理中转程序,效率是很低的。



  国外有人尝试用 Flash 做 JavaScript 和 AJAX 跨域访问中转,无疑是一个好方法。JavaScript 将数据提交给本域下的 Flash,通过 Flash 中转去访问其他域的接口,条件只需要其他域的根目录下有一个crossdomain.xml文件,文件中设置允许所有域名或允许本域访问即可。很多网站的API域名都提供了crossdomain.xml文件。

  例如:
  1、新浪博客的crossdomain.xml文件(http://blog.sina.com.cn/crossdomain.xml)设置了允许所有域名访问;
  2、饭否API的crossdomain.xml文件(http://api.fanfou.com/crossdomain.xml)设置了允许所有域名访问;
  3、校内网API的crossdomain.xml文件(http://api.xiaonei.com/crossdomain.xml)设置了允许所有域名访问;
  4、优酷网的crossdomain.xml文件(http://www.youku.com/crossdomain.xml)设置了允许所有域名访问;
  5、土豆网的crossdomain.xml文件(http://www.tudou.com/crossdomain.xml)设置了允许所有域名访问;

  6、逍遥视频的crossdomain.xml文件(http://v.xoyo.com/crossdomain.xml)设置了只允许*.xoyo.com域名访问;
  7、网易的crossdomain.xml文件(http://www.163.com/crossdomain.xml)设置了只允许tech.163.com、sports.163.com等几个域名访问。



  本人在“Cross-domain AJAX using Flash”的基础上,增加了对表单进行智能处理的功能,封装了一个JavaScript包:AJAXCDR。通过 AJAXCDR,即可轻松地解决 JavaScript 和 AJAX 跨域 HTTP POST/GET 表单请求,支持IE、Firefox、谷歌Chrome等多种浏览器。

  AJAXCDR 拥有两个文件:ajaxcdr.js 和 ajaxcdr.swf,AJAXCDR 拥有一个 JavaScript 函数 AjaxCrossDomainRequest() 和一个全局变量 AjaxCrossDomainResponse。

  一、AJAXCDR 下载:
  http://blog.zyan.cc/demo/ajaxcdr/ajaxcdr-1.0.zip  
  注意:请编辑ajaxcdr.js,查找“/demo/ajaxcdr/ajaxcdr.swf”,将这段Flash文件路径换成您的路径。


  二、AJAXCDR 函数说明:
  1、JavaScript函数:
  AjaxCrossDomainRequest(URL, Method, FormName, CallBack);

  参数说明:
  URL:需要访问的URL地址,相当于表单的action=的值。
  Method:方法,本函数支持POST和GET方法,相当于表单的method=的值。
  FormName:表单名称,相当于表单的name=的值。
  CallBack:回调函数,请求完成后,回调用户的一个函数,用户可以在该函数内对返回值进行处理。

  2、JavaScript全局变量:
  AjaxCrossDomainResponse
  当用户调用AjaxCrossDomainRequest()函数完成 HTTP POST/GET 请求后,该函数会把服务器端返回的数据写入到AjaxCrossDomainResponse变量中,您可以通过AjaxCrossDomainResponse变量获取返回值。


  三、AJAXCDR 应用实例:
  1、实例一(简单演示):
  演示地址: http://blog.zyan.cc/demo/ajaxcdr/demo1.html
  echo.php 源代码为:http://api.bz/ajaxcdr/echo.txt
  crossdomain.xml 文件为:http://api.bz/crossdomain.xml


  2、实例二(复杂表单演示):
  演示地址: http://blog.zyan.cc/demo/ajaxcdr/demo2.html
<html>
<head>
<title>Ajax 跨域 HTTP POST/GET 访问请求演示:Ajax Cross Domain HTTP POST/GET Request Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
<!--
body,td,th {
  font-size: 14px;
}
-->
</style>
</head>
<body>
<form name="cross_domain_demo">
<table width="600" border="1">
  <tr>
    <td colspan="2" align="center" valign="top"><strong>Ajax 跨域 HTTP POST/GET 访问请求演示(鼠标右键查看HTML源代码)</strong></td>
  </tr>
  <tr>
    <td colspan="2" align="center" valign="top">函数说明与下载地址:<a href="http://blog.zyan.cc/ajaxcdr/" target="_blank">http://blog.zyan.cc/ajaxcdr/</a></td>
    </tr>
  <tr>
    <td align="right" valign="top">username</td>
    <td><input name="title" type="text" value="用户名"></td>
  </tr>
  <tr>
    <td align="right" valign="top">password</td>
    <td><input name="password" type="password" value="123456"></td>
  </tr>
  <tr>
    <td align="right" valign="top">content</td>
    <td><textarea name="content" cols="58" rows="5">文本区域值</textarea></td>
  </tr>
  <tr>
    <td align="right" valign="top">city</td>
    <td>
    <select name="city">
        <option value="北京">北京</option>
        <option value="上海">上海</option>
        <option value="深圳">深圳</option>
      </select>  </td>
  </tr>
  <tr>
    <td align="right" valign="top">interest</td>
    <td>
    <select name="interest[]" multiple>
        <option value="玩游戏">玩游戏</option>
        <option value="踢足球">踢足球</option>
        <option value="看书">看书</option>
    <option value="旅游">旅游</option>
    </select>  </td>
  </tr>
  <tr>
    <td align="right" valign="top">gender</td>
    <td>
    <input type="radio" name="gender" value="男">男
      <input type="radio" name="gender" value="女" >女
      <input type="radio" name="gender" value="未知" checked>未知  </td>
  </tr>
  <tr>
    <td align="right" valign="top">grade</td>
    <td>
    <input type="checkbox" name="grade[]" value="等级一">等级一
    <input type="checkbox" name="grade[]" value="等级二">等级二
    <input type="checkbox" name="grade[]" value="等级三">等级三
    <input type="checkbox" name="grade[]" value="等级四">等级四  </td>
  </tr>
  <tr>
    <td align="right" valign="top">publish</td>
    <td><input type="checkbox" name="publish" value="发布">发布</td>
  </tr>
  <tr>
    <td align="right" valign="top">&nbsp;</td>
    <td>
    <a href="javascript:AjaxCrossDomainRequest('http://api.bz/ajaxcdr/echo.php', 'POST', 'cross_domain_demo', 'mycallback(\'参数①\', \'参数②\', myparam)');"><img src="post_button.gif" width="100" height="24" align="absmiddle" border="0"></a>
    &nbsp;&nbsp;  
    <button onClick="AjaxCrossDomainRequest('http://api.bz/ajaxcdr/echo.php', 'GET', 'cross_domain_demo', 'mycallback(\'参数①\', \'参数②\', myparam)'); return false;">GET方式提交</button>
  </td>
  </tr>  
</table>
</form>
<table width="600" border="1">
  <tr>
    <td>JavaScript POST/GET 跨域提交信息到:http://api.bz/ajaxcdr/echo.php (<a href="http://api.bz/ajaxcdr/echo.txt" target="_blank">源代码</a>) </td>
  </tr>
  <tr>
    <td><strong>api.bz服务器端返回信息:</strong></td>
  </tr>
  <tr>
    <td><div id="return_info"></div> </td>
  </tr>
</table>

<script type="text/javascript">
var myparam = "参数③";
function mycallback(param1, param2, param3){
    //提示:AjaxCrossDomainResponse是一个全局变量,它的值为远程服务器的返回值。
    document.getElementById('return_info').innerHTML = "<pre>" + param1 + param2 + param3 + "<BR>" + AjaxCrossDomainResponse + "</pre>";
}
</script>
<script type="text/javascript" src="/demo/ajaxcdr/ajaxcdr.js"></script>
</body>
</html>
  echo.php 源代码为:http://api.bz/ajaxcdr/echo.txt
  crossdomain.xml 文件为:http://api.bz/crossdomain.xml




技术大类 » PHP/JS/Shell | 评论(89) | 引用(0) | 阅读(120013)
james Email
2010-2-1 19:19
我需要在一个网站去另一个网站取RSS
1、返回的是xml,该怎么办?
2、无表单发出get请求,该怎么办?
331   for(var i=0;i<form.length;i++){
373   fs.XmlHttp(urlget, "displayResponse", method, "", contentType);
这两个地方就会出问题
UQ800
2010-3-7 22:14
楼主是否尝试过获取www.baidu.com页面内容?
好像不可以,能否介绍一下?
nttdocomo Email Homepage
2010-4-2 12:23
每种跨域方法都有它的局限性和有点,jsonp和iframe都需要服务器端可控,jsonp需要有callback,iframe需要window.name。所以,只有适合的,没有最好的!
cychai Email Homepage
2010-4-2 17:40
由于编码格式的问题,导致在IE下会报错,同时由于和jQuery 冲突,我对你的js文件进行了修改,博客地址是http://blog.csdn.net/spring21st/archive/2010/04/02/5445520.aspx, 修改后的js文件下载地址 是http://spring21st.download.csdn.net/

请多多指教~~
sadf Email Homepage
2010-4-9 16:28
路过  打酱油
2010-5-4 17:39
还要做的工作很多,比如 如果要POST数据必须使用表单,可否不使用表单呢
mufeng
2010-5-18 10:55
LZ的理念不错,但是我觉得这个JS写得有些复杂。
不过,还是要向LZ学习。
a280238558 Email Homepage
2010-5-18 14:40
你好我按照你上面的方法做了一下,在IE8下出错
“对象不支持此属性和方法”  
//POST请求方式
  fs.XmlHttp(url, "displayResponse", method, body, contentType);
在火狐下面没问题,怎么解决,如果解决请发到我邮箱wanghao19871030@sina.com
WENWEN Homepage
2010-7-28 15:27
很强大  很厉害 www.coo6.com.cn 酷6时尚网
linqi Email
2010-8-12 10:33
flash 的路径,可以是二级域名吗?或者是其它的域名吗?
sink
2010-10-13 14:04
博主,你好。我把swf放在本地可以,即var swfName = "/ajaxcdr.swf";
放在远端就不可以了,即var swfName = "http://example.com/ajaxcdr.swf";
有空指点下,谢谢了。
尘埃
2011-3-31 23:50
能否提供gb2312版的swf?我需要ajax获取静态页面,而静态页面是gb2312编码的~非常感谢!
尘埃 Homepage
2011-4-9 04:25
gbk编码静态页面的问题我自己解决了:http://blog.riubin.com/articles/122
包内附AS源码,后来的兄弟也可以自己修改!
实得分 Email Homepage
2011-4-17 15:30
不错,很强大啊
f903 Email Homepage
2011-6-27 11:41
发现GET或者POST之前会先获取一下crossdomain.xml ,如果没有的话就停止了
能否不get这个文件,直接读取呢?
aimi Email Homepage
2011-8-16 17:47
jsonp简单方便。而且可控性强点。
有点问题!
2011-10-16 09:43
在和jQuery结合使用的过程中,有几个地方是需要注意的:

1. 首先,也是最重要的: crossdomain.xml 放置的位置为跨域的网站所在站点的根目录(注意:不是网站的根目录)。比方说A站点跨域请求B站点的内容,那么,crossdomain.xml 必须放置在B站点的根目录下。



2. 原来的ajaxcdr.js  编码格式 ANSI编码,需将此编码格式更改为UTF-8 编码格式。否则在IE中会出现fs.XmlHttp  “object doesn't support this property or method” 的错误


3. 页面引用 ajaxcdr.js 记得放在页面的最后边</body> 结束符之前。否则,在IE下无法生效

------------------
上面是我网上找的对你的东西的评价~照做后bug没了~
不过我也有点个人建议!就是如果没有form,直接就是想请求些资源,也会遇到跨域的,这个jquery-jsonp虽然可以搞定,但是返回的东西除了资源,还要返回回调函数,我不想两个技术都用,想干脆全用这个ajaxcdr,但是这个form的id我设置""和null都不可以,希望楼主把这个考虑进去,当然我只好自己动手改改你的源码了!
有点问题!
2011-10-16 10:13
我是这么改的~有相同需求且看到这里的可以参考一下!
在ajaxcdr.js文件中搜索"AjaxCrossDomainRequest",然后把var form=document.forms[formname];
    
    for(var i=0;i<form.length;i++){
      //如果是单选按钮、复选框、单选下拉框
      if (form.elements[i].type == "radio" || form.elements[i].type == "checkbox" || form.elements[i].type == "select" ) {
        if(form.elements[i].checked && form.elements[i].name != ""){
          body += encodeURI(form.elements[i].name) + '=' + encodeURI(form.elements[i].value) + '&';
        }
      }
      //如果是多选下拉框
      else if (form.elements[i].type == "select-multiple" && form.elements[i].name != "") {
        for(var sm=0;sm<form.elements[i].length;sm++){
          if(form.elements[i][sm].selected) {
            body += encodeURI(form.elements[i].name) + '=' + encodeURI(form.elements[i][sm].value) + '&';
          }
        }
      }
      //Button、Hidden、Password、Submit、Text、Textarea等文本类型
      else {
        if (form.elements[i].name != "") {
          body += encodeURI(form.elements[i].name) + '=' + encodeURI(form.elements[i].value) + '&';
        }
      }
    }

用  if(formname!=null){}包裹一下!
这样在用的时候就可以直接把formnam写null了!
<a href="javascript:AjaxCrossDomainRequest('http://, 'POST',null, 'mycallback()');">提交</a>
babc Homepage
2011-10-25 12:50
能不能得到301地址!或者header头信息!
yan
2011-10-27 10:54
jsp的提交到https的怎么不起作用,一点反应都没有?
jsp的能用吗?
分页: 3/5 第一页 上页 1 2 3 4 5 下页 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]