AS3的Base64编码和解码
最近要做一个将flash截的图传给js显示的功能,然后需要解决将图片数据转换成Base64编码格式,同事帮忙在网上找到了这个很有用的Base64编码和解码的类。很好用。记录一下。
参考链接:http://www.cordyblog.cn/?action=show&id=49
调用代码:
import com.dynamicflash.utils.Base64;
//编码和解码字符串
var source:String = "Hello, world";
var encoded:String = Base64.encode(source);
trace(encoded);
var decoded:String = Base64.decode(encoded);
trace(decoded);
//编码和解码ByteArray
var obj:Object= {name:"Dynamic Flash",url:"http://dynamicflash.com"};
var source:ByteArray = new ByteArray();
source.writeObject(obj);
var encoded:String = Base64.encodeByteArray(source);
trace(encoded);
var decoded:ByteArray = Base64.decodeToByteArray(encoded);
obj = decoded.readObject();
trace(obj.name + "(" + obj.url + ")");
Base64类代码:
package com.dynamicflash.util{
import flash.utils.ByteArray;
public class Base64 {
private static const BASE64_CHARS:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
public static const version:String = "1.0.0";
public static function encode(data:String):String {
// Convert string to ByteArray
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(data);
// Return encoded ByteArray
return encodeByteArray(bytes);
}
public static function encodeByteArray(data:ByteArray):String {
// Initialise output
var output:String = "";
// Create data and output buffers
var dataBuffer:Array;
var outputBuffer:Array = new Array(4);
// Rewind ByteArray
data.position = 0;
// while there are still bytes to be processed
while (data.bytesAvailable > 0) {
// Create new data buffer and populate next 3 bytes from data
dataBuffer = new Array();
for (var i:uint = 0; i < 3 && data.bytesAvailable > 0; i++) {
dataBuffer[i] = data.readUnsignedByte();
}
// Convert to data buffer Base64 character positions and
// store in output buffer
outputBuffer[0] = (dataBuffer[0] & 0xfc) >> 2;
outputBuffer[1] = ((dataBuffer[0] & 0x03) << 4) | ((dataBuffer[1]) >> 4);
outputBuffer[2] = ((dataBuffer[1] & 0x0f) << 2) | ((dataBuffer[2]) >> 6);
outputBuffer[3] = dataBuffer[2] & 0x3f;
// If data buffer was short (i.e not 3 characters) then set
// end character indexes in data buffer to index of '=' symbol.
// This is necessary because Base64 data is always a multiple of
// 4 bytes and is basses with '=' symbols.
for (var j:uint = dataBuffer.length; j < 3; j++) {
outputBuffer[j + 1] = 64;
}
// Loop through output buffer and add Base64 characters to
// encoded data string for each character.
for (var k:uint = 0; k < outputBuffer.length; k++) {
output += BASE64_CHARS.charAt(outputBuffer[k]);
}
}
// Return encoded data
return output;
}
public static function decode(data:String):String {
// Decode data to ByteArray
var bytes:ByteArray = decodeToByteArray(data);
// Convert to string and return
return bytes.readUTFBytes(bytes.length);
}
public static function decodeToByteArray(data:String):ByteArray {
// Initialise output ByteArray for decoded data
var output:ByteArray = new ByteArray();
// Create data and output buffers
var dataBuffer:Array = new Array(4);
var outputBuffer:Array = new Array(3);
// While there are data bytes left to be processed
for (var i:uint = 0; i < data.length; i += 4) {
// Populate data buffer with position of Base64 characters for
// next 4 bytes from encoded data
for (var j:uint = 0; j < 4 && i + j < data.length; j++) {
dataBuffer[j] = BASE64_CHARS.indexOf(data.charAt(i + j));
}
// Decode data buffer back into bytes
outputBuffer[0] = (dataBuffer[0] << 2) + ((dataBuffer[1] & 0x30) >> 4);
outputBuffer[1] = ((dataBuffer[1] & 0x0f) << 4) + ((dataBuffer[2] & 0x3c) >> 2);
outputBuffer[2] = ((dataBuffer[2] & 0x03) << 6) + dataBuffer[3];
// Add all non-padded bytes in output buffer to decoded data
for (var k:uint = 0; k < outputBuffer.length; k++) {
if (dataBuffer[k+1] == 64) break;
output.writeByte(outputBuffer[k]);
}
}
// Rewind decoded data ByteArray
output.position = 0;
// Return decoded data
return output;
}
public function Base64() {
throw new Error("Base64 class is static container only");
}
}
}
unload
http://gskinner.com/blog/archives/2008/04/failure_to_unlo.html
Flash Debug Player引起Firefox 3.6崩溃的解决办法
调试Flash的时候,只要有异常,弹出异常窗口以后,Firefox就不响应了,过一会会显示Flash插件崩溃的信息,只能通过任务管理器强行关闭Firefox。
解决方案如下:
1. Firefox地址栏输入about:config,打开高级设置,如果有警告直接忽略
2. 在Filter里搜索dom.ipc.plugins
3. 双击dom.ipc.plugins.enabled.npswf32.dll设为false
4. 也可以把dom.ipc.plugins.timeoutSecs设为-1来禁用插件崩溃的timeout
5. 重启Firefox
谷歌账户无法登陆,网络连接失败的解决方法
参考链接地址:http://bbs.gfan.com/viewthread.php?tid=1210600&extra=pageD1&page=1
和同事换过sim卡后,谷歌账号就登陆不上了,其他网络链接正常,GMAIL的网页版也能登上,估计就是手机账号登陆的地址被墙,
看了参考链接的解决方法后,就开始报着试一试的态度去验证下。说实话如果不是天天看着那个三角叹号烦人,我才不这么麻烦的去解决它。
解决方法:1.下载R.E.管理器,挂载为读写模式
2.在etc目录下找到hosts文件,以文本编辑模式打开。
3.编辑host文件里
209.85.135.100 clients2.google.com
209.85.135.101 android.l.google.com
209.85.135.102 android.clients.google.com
为
74.125.53.100 clients2.google.com
74.125.53.101 android.l.google.com
74.125.53.102 android.clients.google.com
4.重启后试登陆,其他人的可以,我的还是不可以,后来才发现是我设置——>账号和同步——>背景数据没有勾上,勾上后再试登陆,居然ok了,感谢发帖的人和回帖的人们。
总结,下次如果再遇到这个问题,可以现在电脑上ping一下hosts里面登陆相关的ip是否还能ping通,不能ping通的话可以找个能ping通的地址写上,这个问题就能解决了。
win7下不能正常卸载air的解决方法
以前在win7下装了个air,后来不知咋整的,怎么也卸载不了,更新也更新不了,没辙,只好想了个暴力卸载的招。
1.找到其安装目录:C:\Program Files\Common Files\Adobe AIR
删除整个文档,如果你怕有问题,可以先备份下。
如果删除时提示被其他程序占用,可以使用附件->系统工具->资源监视器,在CPU选项卡的关联句柄中搜索adobe air,就可以找到是哪个进程占用了,然后右键结束。
2.删除所有adobe air相关的注册表信息,如果怕删错,可以先备份一下注册表。
3.安装新的adobe air程序即可。
FLASHDEVELOP配置(转)
一、基本环境:Flash CS4、net framework 2.、Flex SDK4.0、Java SDK 1.6、FlashDevelop
二、基本配置:
①Tools → Program Settings → ASCompletion → Flash IDE ,检查一下是否指对了正确的Flash CS4安装路径。
②Tools → Program Settings → AS3Context → Language → Flex SDK Location,指向你的Flex路径。
③打开工程属性(project Properties)在“Compiler Options”那个选项卡里,展开“Additional Compiler Options”那个小加号[0]后那一项添加 : -static-link-runtime-shared-libraries=true
④FlashDevelop导入FL包的办法:复制FlashDevelop\Library\AS3\frameworks\FlashIDE下面的FL包到FlashDevelop\Library\AS3\intrinsic\FP10。然后将默认的FLASH发布版本由9改成10。
⑤修改默认字体大小 :默认情况下中文字比较小,看着会比较累。选择 Tools -> Syntax Color… 就可以修改了。注意哦,默认只是改编辑AS3 的字体。
三、使用方法:
A.资源加载
1、外部资源加载
在as3中通常我们在加载外部图片、SWF等外部资源时我使用Loader来进行加载。对于存放在d盘根目录下的一张图片,我们是这样来加载的
[cc lang="actionscript"]var loader:Loader = new Loader();
loader.load(new URLRequest(“d:\pic.jpg”));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
function loadCompleteHandler(e:Event):void{
var bitmap:Bitmap = Bitmap(e.target.content);
addChild(bitmap);
}[/cc]
2、 FD中的资源加载
因为FD中是用FlexSDK来进行编译,所以除了使用上述的加载方式外,在FD中还可以使用嵌入的方式加载图片,swf,字体等外部资源。
图片加载:
在项目文件夹lib上单击鼠标右键,在弹出菜单中选择Add(添加)–>Library Asset(库资源)…
在打开的选择框中,从本地选择一张图片文件添加到项目
在代码中添加一个Class对象:Private var Pic:Class
在刚才加入的图片文件上单击鼠标右键,选择Insert Into Document(插进文档)
在代码中会出自动添加一行,如下[Embed(source=’..lib/img.jpg’)]
接下来我们把它添加到舞台上,再看看效果addChild(new Pic())
SWF的加载:
swf的加载也同样如此,我们选择一个文件导入到项目
接下来我们创建一个swf中的元件,将他添加到舞台上
[cc lang="actionscript"]
[Embed(source='../lib/Movie.swf',mimeType='application/x-shockwave-flash',symbol='RectMc')]
//symbol=’RectMc’为Movie.swf中一个元件(Class)
private var SWF:Class;[/cc]
其中
mimeType=’application/x-shockwave-flash’
注意不要写成
mimeType=’application/octet-stream’
字体的加载:
字体的加载略有不同,我们导入一个字体文件到项目中
[cc lang="actionscript"][Embed(source=’’,font=’cc’)]
Private var font:Class
//这里我们创建一个TextField来使用这个字体,fontName是自己设定的
Var tf:TextField=new TextField()
Var ff:TextFormat=new TextFormat(“cc”,20)[/cc]
注意上面代码里的 tf.embedFonts = true,这里一定要设为true,才会有效,不设为true的话字体为默认字体
资源嵌入的方式很好用,但是由于把资源编译到了swf文件内,发布后的swf文件就会相对来说大很多了.
SWC的使用
SWC的导入跟图片的导入一样,我们选择一个SWC导入到项目
点击它前面的“+”,我们可以看到它里面所包含的类和元件
在SWC文件上单击鼠标右键,可以看到Add To Library这一项是被选上了的,只有当这一项被选中时,我们才能使用它,IDE中也才能感应到它
B使用技巧
1、使用trace
要使用Trace,使用的FlashPlayer必须是具有debug功能的,我们能在FlexSDK中找到一个。如果直接使用不行,可以再设置一下。
打开Program Settings面板,选择FlashViewer,将其中的External Player Path设定为指向Flex SDK中的FlashPlayer,windows中它的路径通常为:你的FlexSDK目录\runtimes\player\win\FlashPlayer.exe”,其中还有Linux,MacOS中使用的FlashPlayer。设置好后我们就可以使用trace了。
2、关于OutputPanel
如果我们Coding时,喜欢让其他的窗口都隐藏起来,在调式时对于我们trace出来的一些信息就不方便观察。在Flash CS3中,每当有新信息出来的时候,都会将output窗口置到最上面。在FD中,我们也可以设置一下,当有信息出现时,自动将OutputPanel弹出。
从菜单选择Tools -> Program Setting…
在面板的左边找到OutputPanel的选项,在右边将两个属性都设置为True。这样,在我们调式的时候一有信息输出,OutputPanel就会弹出来了。
3、关于XML和XMLList
大家可能发现在FlashDevelop里使用XML以及XMLList时,不象使用其他类那样可以“.”出他的属性和方法,这或许是FlashDevelop的Bug吧。不过我们可以通过使用快捷键“Ctrl+Space”来手动让他显示出来。
4、自定义Project模板
在我们新建项目的时候,你会发现程序会为我们自动生成一些文件夹和文件,其实这些都是在模板里面设置好的,我们可以更改这些模板来适合自己的习惯。比如增加API文件夹。
从菜单选择Tools–>Application Files…打开文件夹
找到AS3 Project的模板:\Templates\ProjectTemplates\120 ActionScript 3 – AS3 Project\
例如需要找到
D:\ProgramFiles\FlashDevelop\Projects\120ActionScript3-AS3Project\src\$(PackagePath)
选择项目文件打开
可以看到两个模板文件,以及一个说明文件Project.txt,我们可以修改模板文件Main.as.template
在模板中添加了几行,现在新建一个AS3项目就能看到刚才添加进去的内容了。
比如改为:
[cc lang="actionscript"]
package $(PackageName)$(CSLB){
/**
$(CBI)* @author $(DefaultUser)
$(CBI)* @email $(DefaultEmail)
$(CBI)* @date $(Timestamp)
$(CBI)**/
import flash.display.Sprite;
import flash.events.Event;
//[SWF(width="550",height="400",frameRate="24",backgroundColor="#ffffff")]
public class Main extends Sprite $(CSLB){
public function Main():void $(CSLB){
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void $(CSLB){
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}
}
}
[/cc]
除此之外你还可以添加文件夹、文件、类或者其他你需要的东西。
但新建类的模板在:D:\Program Files\FlashDevelop\Templates\ProjectFiles\AS3Project这个文件夹下的Class.as.fdt.wizard
比如:
[cc lang="actionscript"]package $(Package) $(CSLB){
/**
$(CBI)* @author $(DefaultUser)
$(CBI)* @email $(DefaultEmail)
$(CBI)* @date $(Timestamp)
$(CBI)**/
$(Import)
$(Access)class $(FileName)$(Extends)$(Implements)$(CSLB){
public function $(FileName)($(ConstructorArguments)) $(CSLB){
$(Super)$(EntryPoint)
}
}
}[/cc]
5、关于Debug/Release
在我们编译项目时,可以选择debug或者release,但是有时候我们可能会不知道或不记得我们最后生成的版本是debug版的还是release版的。不过,我们有办法解决这个问题。
打开项目属性面板Project -> properties…
在Output file里,将生成的文件名后加上“-debug”,就象下面这样
General
Outfile:bin/newproject-debug.swf
设置好以后,当我们选择debug时,项目会生成NewProject-debug.swf,选择release时会生成NewProject.swf。这样,我们就把两个版本分开了。
6、常用快捷键
F1: 当你看见在提示中有“…”时,你可以按F1键来获得更多的帮助
Ctrl+Space: 显示代码提示框
Ctrl+D: 复制当前行
把光标移动到onEnterFrameHandler上,按下Ctrl+Shift+1,选择Generate Event handler后,就回自动生成我们想要的函数,其他的代码生成方法也类似,只要在需要的地方按下快捷键,就会出现提示,选择提示框中的选项就能生成我们想要的代码了。
7、语法配色文件
D:\Program Files\FlashDevelop\Settings\Languages\AS3.xml
8、生成API
setting—-ASDoc Location—-D:\Program Files\flex\bin
Project—-Compiler—ASDOC(as3)
9、修改as3语言帮助为本地帮助(cs5)
D:\Program Files\FlashDevelop\Settings\MainMenu.XML
[cc lang="xml"]
[/cc]
10.使用fl包
指定项目类路径:Program Files\Adobe\Adobe Flash CS4\Common\Configuration\ActionScript 3.0\projects\Flash\src
或者嵌入swc:flswc.swc
转自:http://www.cnblogs.com/ddw1997/archive/2010/05/17/1737043.html
Flash XMLSocket 通信问题总结(转)
Flash XMLSocket 通信问题总结
1、前言
本文以标准两层 C/S 架构为例,对 XMLSocket 通信编程作一沉痛总结。
从开始到调试正常耗掉了我几乎一周的时间,故为沉痛!尚东!!真是太尚东了!!!
为方便描述,把 Flash Player 称作客户端(Client),包括独立的 Player 和嵌入浏览器的 Player。
2、用途
XMLSocket 类提供以 TCP/IP 方式进行程序间通讯的功能。
3、开发基本流程
流程无所谓,先做服务端也好,先做客户端也罢,都不可能把一边做完再做另一边,总之是要同步进行,除非服务端已经存在。
4、客户端开发
XMLSocket 类使用比较简单,基本上就是几个步骤:
1) 创建 XMLSocket 类的实例。
2) 写好需要响应的事件代码,事件很少,如下:
onConnect: Socket 成功连接后触发,传入一个参数,指定连接状态
onClose: 服务器端断开 Socket 后触发
onData: 收到服务端数据,或传输错误时触发,传入一个参数,为 undefined 时表示传输错误,否则为收到的数据
onXML: 收到服务端 XML 内容,或传输错误时触发,参数同 onData
典型的代码片段如下:
…
var g_Socket = new XMLSocket();
g_Socket.onConnect = ge_OnConnect;
g_Socket.onClose = ge_OnDisconnect;
g_Socket.onData = ge_OnData;
…
3) 通过调用 connect( 服务端地址或IP, 服务端口 ) 方法发起连接请求。
4) 连接若成功,数据的收发处理就由自己决定了。
5、服务端开发
服务端根据情况可选各种语言开发,如 Java/C++/C#,只要能处理 Socket 的就行。
个人感觉,开发前期可用 C++/单线程,输出和调试都方便,等通信层稳定后,可考虑用 Java 实现管理逻辑,在线程安全、垃圾回收、锁等方面,Java 都比 C++ 来得方便。
根据应用的不同,服务端的具体实现千变万化,但基本的工作原理和内容是类似的:
1) 初始化内部数据
2) 开始监听端口
3) 处理连接请求
4) 管理会话(Session)
5) 管理线程
6) 收集和分发数据
7) 实现业务逻辑
再展开来还有网络连接池、数据连接池、线程池、交互锁等。
6、沙箱和安全策略问题
此问题发生在连接时,准确地说是连接前,分别两种情况:
6.1.1、本地播放
本地播放时,默认情况下 Flash Player 将不允许 swf 访问任何网络。
访问 http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html,将 swf 加入到许可列表,即可解除限制。
6.1.2、WEB 发布
发布在 WEB 上的 swf, 将可能面临跨域的问题。
Flash 中的通信方式有两种:
1) HTTP 方式:如 URLLoader 等用于加载远程 swf、文件、图像、音视频流。
2) Socket 主要:如 XMLSocket,用于与远程服务端建立长效连接。
Flash Player 6 以上版本引入了安全策略文件,在进行正式的通信前,会检查目标位置是否存在合法的安全策略,以防止不同域内的应用无限制任意互访。
HTTP 方式下,Flash Player 会检查目标域根目录下是否存在 crossdomain.xml,如果有,则获取并分析其内容(内容后述)以确定是否允许继续访问。
Socket 方式下,Flash Player 获取安全策略稍微复杂些,从 9.0.115.0 版起,标准步骤如下(以下描述以 IE 为标准,例外情况后述):
1) 首先向目标主机 843 端口发起连接,并发送一个字符串,内容为 “
2) 若 1) 失败,则检查 AS 代码中是否使用了 Security.loadPolicyFile( “xmlsocket://主机:端口” ) 方法加载安全策略文件,若有,则获取并分析。
3) 若 2) 失败,则向 AS 代码中即将连接的 “目标主机:端口” 发起请求,过程同 1)。
4) 若成功获得安全策略文件并经分析认为允许建立连接,则继续执行 Connect() 方法,此时方真正尝试创建与目标主机的连接。
6.1.3、解决方案
了解了上面说到的问题,解决方案便呼之欲出了,HTTP 连接方式不用再说,只说说 Socket 方式。
1) 在服务端写一个程序,监听 843 端口,当收到 “
2) 在 AS 中通过 loadPolicyFile() 加载策略文件,此处需注意使用 xmlsocket:// 而不是 http://。
3) 在标准服务端口中,检测到 “
6.1.4、例外情况及测试结果
经测试发现,在 IE, Opera 中,Flash Player 会严格按上述步骤检查安全策略。
在 FireFox, Chrome 中发起连接时,Flash Player 并不会向服务端发送 “
7、数据传输中的问题
在 XMLSocket 数据传输中,需要注意以下细节,否则会出来些莫名其妙的问题。
7.1、结束符号
XMLSocket 接收到服务端下发的数据时,将连续放于接收缓冲区,直到接收到 “\0″ 字节(字节内容为 ASCII 值 0),才认为接收完成,并调用相应的 onData 或 onXML 事件。
服务端若用 Java 编写,并使用标准的 String 类族,则在发送数据结尾应手动加上 “\0″。
若用 C++ 编写,由于 C++ 中标准字符串类型便是以字节 0 作结束标记,故不必再加 “\0″。
* C++ 中需注意另一个问题,若自行进行了字符串处理,在决定字符串长度时,标准的 strlen 及 String.Length() 等返回的均是实际有效字符个数,最终向网络发送时,总长度应加 1 字节,以容纳结尾的字节 0。
* 此问题在发送安全策略内容时同样存在,故需重视。
7.2、中文问题
默认情况下,不管从哪一端发向另一端的数据,若包含了中文字符,都会产生乱码的现象,解决方法有二:
1) 在 AS 中加入 “System.useCodepage = true;” 强制使用本地代码集,此法最方便,但是在跨语种平台上仍会出现乱码。
2) 在代码中自行编写转码函数,此法复杂些,但通用性强。具体转码算法网上很多,主要是 C++ 服务端需要,Java 中使用 JDK 类转换为 UTF-8 即可。
来自: http://hi.baidu.com/wwwanq/blog/item/52e29530e5c7cca05fdf0e1d.html
error while loading initial content的解决方案(转)
现在国内的flash builder4能学习的源码很少.E文是相对一部分人来说的.所以还有不少人在使用FLEX3的源码来学习研究.有人会在开始用flash builder4时碰到以下这个问题.其实解决方法跟以前FLEX3一样.
举例:
导入一个完整的Flex3源码进Flash Builder4里,准备调试看效果.其中出现如下窗口
——————————————————————–
Process terminated without establishing connection to debugger.
Command:
“C:\Program Files\Adobe\Flex Builder 3\sdks\3.2.0\bin\adl.exe”
C:\adobeFlexTraining\flex3test\search\bin-debug\downloader-app.xml
C:\adobeFlexTraining\flex3test\search\bin-debug
Output from command:
error while loading initial content
———————————————————————-
解决方法:
打开 downloader-app.xml 配置文件
将Application 修改为下面的一行, 重新编译保存.
对应版本
flex sdk 3.0.0的改成 1.0
flex sdk 3.2 的改成 1.5
flex sdk 4.0 的改成 1.5.3
以后的版本也是同样方法.
出自:http://perusal2008.blogbus.com/logs/49397110.html
AS3——navigateToURL(转)
navigateToURL() 可以用来打开一个新的浏览器窗口,也可以用来flex和js之间的通信,比如打开一个新窗口:
var url:URLRequest = new URLRequest("http://www.eb163.com");
navigateToURL(url, "_blank");
这个函数也可以用来执行js,例如:
var url:URLRequest = new URLRequest(“javascript:window.close()”);
或者:
var urlLURLRequest = new URLRequest(“javascript:myFun(para1…paran)”)
myFun()函数是html页面的script部分定义的,函数参数一定要有引号!
navigateToURL(url, "_self");
也可以用来发送email:
var urlURLRequest = new URLRequest("mailto:55555@163.com");
navigateToURL(url, "_blank");
阻止navigateToURL弹窗的解决方法:
package FlashCode.utils{
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.external.ExternalInterface;
public class openWindow {
public function openWindow(url:String, window:String="_blank", features:String=""){
var WINDOW_OPEN_FUNCTION:String = "window.open";
var myURL:URLRequest = new URLRequest(url);
var browserName:String = getBrowserName();
if(getBrowserName() == "Firefox"){
ExternalInterface.call(WINDOW_OPEN_FUNCTION, url, window, features);
}
//If IE,
else if(browserName == "IE"){
ExternalInterface.call(WINDOW_OPEN_FUNCTION, url, window, features);
//ExternalInterface.call("function setWMWindow() {window.open('" + url + "');}");
}
//If Safari
else if(browserName == "Safari"){
navigateToURL(myURL, window);
}
//If Opera
else if(browserName == "Opera"){
navigateToURL(myURL, window);
} else {
navigateToURL(myURL, window);
}
/*Alternate methodology...
var popSuccess:Boolean = ExternalInterface.call(WINDOW_OPEN_FUNCTION, url, window, features);
if(popSuccess == false){
navigateToURL(myURL, window);
}*/
}
private function getBrowserName():String{
var browser:String;
//Uses external interface to reach out to browser and grab browser useragent info.
var browserAgent:String = ExternalInterface.call("function getBrowser(){return navigator.userAgent;}");
// Debug.text += "Browser Info: [" + browserAgent + "]";
//Determines brand of browser using a find index. If not found indexOf returns (-1).
if(browserAgent != null && browserAgent.indexOf("Firefox") >= 0) {
browser = "Firefox";
}
else if(browserAgent != null && browserAgent.indexOf("Safari") >= 0){
browser = "Safari";
}
else if(browserAgent != null && browserAgent.indexOf("MSIE") >= 0){
browser = "IE";
}
else if(browserAgent != null && browserAgent.indexOf("Opera") >= 0){
browser = "Opera";
}
else {
browser = "Undefined";
}
return browser;
}
}
}
跨域资源共享的10种方式(转)
http://www.woiweb.net/10-cross-domain-methods.html
在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?
同源策略
在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域。比如http://www.example.org/index.html和http://www.example.org/sub/index.html是同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何两个都将构成跨域。同源策略还应该对一些特殊情况做处理,比如限制file协议下脚本的访问权限。本地的html文件在浏览器中是通过file协议打开的,如果脚本能通过file协议访问到硬盘上其它任意文件,就会出现安全隐患,目前IE8还有这样的隐患。
受到同源策略的影响,跨域资源共享就会受到制约。但是随着人们的实践和浏览器的进步,目前在跨域请求的技巧上,有很多宝贵经验的沉淀和积累。这里我把跨域资源共享分成两种,一种是单向的数据请求,还有一种是双向的消息通信。接下来我将罗列出常见的一些跨域方式,以下跨域实例的源代码可以从这里获得。
单向跨域
JSONP
JSONP (JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签可以加载并执行其他域的JavaScript,于是我们可以通过script标记来动态加载其他域的资源。例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完之后会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行,那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。
flash URLLoader
flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助Flash来发送HTTP请求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把www.a.com加入到白名单。其次,通过Flash URLLoader发送HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就无能为力了。
Access Control
Access Control是比较超越的跨域方式,目前只在很少的浏览器中得以支持,这些浏览器可以发送一个跨域的HTTP请求(Firefox, Google Chrome等通过XMLHTTPRequest实现,IE8下通过XDomainRequest实现),请求的响应必须包含一个Access-Control-Allow-Origin的HTTP响应头,该响应头声明了请求域的可访问权限。例如www.a.com对www.b.com下的asset.php发送了一个跨域的HTTP请求,那么asset.php必须加入如下的响应头:
header(“Access-Control-Allow-Origin: http://www.a.com”);
window.name
window对象的name属性是一个很特别的属性,当该window的location变化,然后重新加载,它的name属性可以依然保持不变。那么我们可以在页面A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,页面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。这个方式非常适合单向的数据请求,而且协议简单、安全。不会像JSONP那样不做限制地执行外部脚本。
server proxy
在数据提供方没有提供对JSONP协议或者window.name协议的支持,也没有对其它域开放访问权限时,我们可以通过server proxy的方式来抓取数据。例如当www.a.com域下的页面需要请求www.b.com下的资源文件asset.txt时,直接发送一个指向www.b.com/asset.txt的Ajax请求肯定是会被浏览器阻止。这时,我们在www.a.com下配一个代理,然后把Ajax请求绑定到这个代理路径下,例如www.a.com/proxy/, 然后这个代理发送HTTP请求访问www.b.com下的asset.txt,跨域的HTTP请求是在服务器端进行的,客户端并没有产生跨域的Ajax请求。这个跨域方式不需要和目标资源签订协议,带有侵略性,另外需要注意的是实践中应该对这个代理实施一定程度的保护,比如限制他人使用或者使用频率。
双向跨域
document.domain
通过修改document的domain属性,我们可以在域和子域或者不同的子域之间通信。同域策略认为域和子域隶属于不同的域,比如www.a.com和sub.a.com是不同的域,这时,我们无法在www.a.com下的页面中调用sub.a.com中定义的JavaScript方法。但是当我们把它们document的domain属性都修改为a.com,浏览器就会认为它们处于同一个域下,那么我们就可以互相调用对方的method来通信了。
FIM – Fragment Identitier Messaging
不同的域之间,JavaScript只能做很有限的访问和操作,其实我们利用这些有限的访问权限就可以达到跨域通信的目的了。FIM (Fragment Identitier Messaging)就是在这个大前提下被发明的。父窗口可以对iframe进行URL读写,iframe也可以读写父窗口的URL,URL有一部分被称为frag,就是#号及其后面的字符,它一般用于浏览器锚点定位,Server端并不关心这部分,应该说HTTP请求过程中不会携带frag,所以这部分的修改不会产生HTTP请求,但是会产生浏览器历史记录。FIM的原理就是改变URL的frag部分来进行双向通信。每个window通过改变其他window的location来发送消息,并通过监听自己的URL的变化来接收消息。这个方式的通信会造成一些不必要的浏览器历史记录,而且有些浏览器不支持onhashchange事件,需要轮询来获知URL的改变,最后,URL在浏览器下有长度限制,这个制约了每次传送的数据量。
Flash LocalConnection
页面上的双向通信也可以通过Flash来解决,Flash API中有LocalConnection这个类,该类允许两个SWF之间通过进程通信,这时SWF可以播放在独立的Flash Player或者AIR中,也可以嵌在HTML页面或者是PDF中。遵循这个通信原则,我们可以在不同域的HTML页面各自嵌套一个SWF来达到相互传递数据的目的了。SWF通过LocalConnection交换数据是很快的,但是每次的数据量有40kb的大小限制。用这种方式来跨域通信过于复杂,而且需要了2个SWF文件,实用性不强。
window.postMessage
window.postMessage是HTML5定义的一个很新的方法,这个方法可以很方便地跨window通信。由于它是一个很新的方法,所以在很旧和比较旧的浏览器中都无法使用。
Cross Frame
Cross Frame是FIM的一个变种,它借助了一个空白的iframe,不会产生多余的浏览器历史记录,也不需要轮询URL的改变,在可用性和性能上都做了很大的改观。它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html,A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出message,并移除该iframe。当B.html需要向A.html发送消息时,原理一样。Cross Frame是很好的双向通信方式,而且安全高效,但是它在Opera中无法使用,不过在Opera下面我们可以使用更简单的window.postMessage来代替。
总结
跨域的方法很多,不同的应用场景我们都可以找到一个最合适的解决方案。比如单向的数据请求,我们应该优先选择JSONP或者window.name,双向通信我们采取Cross Frame,在未与数据提供方没有达成通信协议的情况下我们也可以用server proxy的方式来抓取数据。