ActionScript 3.0 中,以数据形式传输图片包的完整解决方案

来源:互联网 发布:三菱plcq系列伺服编程 编辑:程序博客网 时间:2024/05/16 17:14

    初学AS3.0中,想要将多个小图片打成一个二进制数据包,由Flash下载到本地,然后解包显示。这样做有多个好处:

  • 对于一定会一起加载的一堆小图片,减少连接数消耗。
  • 以数据包形式传输,便于加密。
  • 对于形成“组”概念的资源(如一个相册图集),方便管理。

    找了N多资料,发现都是对其中某一点的解决,缺乏整体的方案。so,那就不罗嗦了,我丢一个上来抛砖引玉吧~

    反正是初学,代码里面可能有好多不是最优的地方,反正请高手尽情刨玉、跟我一样的初学者能够有所参考,足矣~

 

    要解决这个问题,我的思路如下:

  • 定义数据包格式
  • 服务器上有一个页面,可以提供二进制图片数据包。
  • 有一个clsPacket类,提供一个getImages的方法,提供图片包地址参数,返回一个包含图片的数组。
  • 一个方法,创建clsPacket的实例,调用getImages方法。设置一个事件监听,在getImages方法执行完成之后,将获得的图片数组丢给显示的方法。
  • 一个将图片数组显示出来的方法,这个就看具体需要了,本例中就是随便加上去以查看结果。

    OK,下面咱们一步一步来解决

 

1、定义数据包格式

    为方便理解,这里定义一个超级简单的数据包格式:

  • 头两个byte,为一个int16值,用于标明这个包内的图片总数。(之所以用int而不是uint,是考虑到负数可以用来标明一些异常状态。此外,根据你的需要,也可以设置为四个byte的int32值)
  • 此后为图片的数据循环,包括:
    • 4个byte标明图片数据长度
    • 实际图片数据
  • 如果还有一些特定数据,比如相册说明什么的,可以标在后面,本例中是没有。

    当然,你也可以定义自己的数据包格式,道理是一样的。

 

2、设置服务器测试环境

    这里我在本地的虚拟目录test下放了一个mutipleImgBinary.aspx文件(基于.NET 3.5,C#)。我们先来看页面:

 

mutipleImgBinary.aspx

 

    对,你没有看错,初始的<html>标签这些已经被删除了,因为我们要做二进制输出么~

    然后咱们再来看代码:

 

mutipleImgBinary.aspx.cs

 

    这个代码非常简单,就是从虚拟目录下的pix目录中找出所有文件来,然后根据刚才设置的数据包格式进行二进制输出。

    这个例子中,需要注意的是:

  • 由于是方便测试,所以是在输出时打包。实际应用中,可以考虑提前将数据打好包,比如上传完图片,这样才能真正节省资源。
  • 如果需要加密,就在打包之后、输出之前进行加密即可。
  • 由于flash的Bitmap不直接支持BMP,所以在pix目录下,请只丢jpeg、gif、png的图片。(当然,后面Flash端如果你做了bmp的支持,就可以不用考虑这一点了)
  • 弱弱地再提一点,pix目录下只丢图片哦!

3、clsPacket类

    这是一个ActionScript类,它实际上可以认为就是一个方法getImages()。但是由于加载机制是托管异步的,所以如果在这个方法中直接返回,那将是返回一个空数组。so,又不得不分为几步来进行处理:

 

    (1) getImages方法:实际上只是获得图片包的地址,创建一个URLLoader来加载数据,然后加一个事件监听器,在完成加载后执行whenDataLoaded方法。

 

    (2)whenDataLoaded方法:将获得的ByteArray 解包,获得数据包中的图片总数,然后一个for循环,将每一个图片数据的开始位置、结束位置和顺序丢给loadImage方法。如果数据包有加密,可以在这一步先解密再解包。

 

    (3)loadImage方法:创建一个新的ByteArray,通过开始位置和结束位置获得单个图片的数据。用Loader来加载,并且放一个事件监听器,等Loader完成,就丢给convert2img方法。(可恶的Loader,本来明明应该可以加载然后转为Bitmap对象的,但是不这么做它就会不等加载完成就开始转,导致失败。)

 

    (4)convert2img方法:将Loader转为Bitmap对象(如果只是Loader的话,就不好去控制width等图片的属性)。如果你想加上对BMP格式的支持,可以在这一步通过文件头数据来判断,然后转换。将Bitmap对象加入数组,然后执行checkLast方法来判断是否最后一张图像都已经转换完成。

 

    (5)checkLast方法:由于Flash的检查加载是否完成这些托管方法都是异步的(从底层来说应该是多线程),就会导致各个Loader加载所用的时间是不同的。它的好处应该是大大提高了效率,坏处则是加入数组的图像都乱序了,而且所有图像加载完成的时间就不确定了。因此,我在数组中加入了index项来保持排序的正确性。在checkLast方法中,通过检查图像数组的长度和图片总数是否相等来判断是否已经加载完成最后一张图片,然后对数组进行排序。此外,最重要的是,加了一个LOADCOMPLETED事件,用dispatchEvent通知外部的事件监听器“所有图片加载完成”。

 

    综上,clsPacket类的成员参数有3个,图像数组(包括index和Bitmap对象)、图像总数、LOADCOMPLETED事件。

 

    OK,代码如下:

 

clsPacket.as

 

 

 4、调用clsPacket

    麻烦的clsPacket搞定以后,就简单多了~我们只需要创建clsPacket实例,设置事件监听器,然后调用显示图片的方法即可。

    比如,我们可以创建一个flash,然后丢一个按钮上去(比如叫作btnShow),设置点击事件:

 

   

     flash中的调用和显示相对来说比较灵活简单,就不多说了。这里需要注意的一点是:虽然是在本机上运行,但是只能使用网络域地址进行调用(如“http://www.xxx.com/....”或者“http://192.168.x.x/...),不能使用本地网络域“http://localhost/....”或“http://127.0.0.1”,否则会引起安全沙箱报错。这是因为我们是以数据形式调用了网络资源,所以受到安全沙箱的限制。

 

    此外,这个例子稍加转换,就可以变成打包加载声音或是其他的资源。想想flash小游戏里面小个小个的音效文件,也许还是会有用的吧~

 

    OK,新的一年里,继续努力追求钱和美女ing,祝大家也好运~~

 

 

 P.S.

1 转载OK,但请注明出处哈~

2 点击Chrome浏览器地址栏右侧的箭头,是可以强制刷新的。对于不停发布flash进行测试来说,是福音啊~~