百度文库技术浅析



百度文库应用      沈龙七QQ 459733390

最近上网总是有人问我百度文库技术或者是flex paper技术。呵呵。其实这个东西没有

想的那么难。就百度文库来说,可以证明无论是adobe的flashpaper还是开源的flash2print

都没有做到那么智能。为什么说智能呢?你分析下你ie里的百度文库里缓存的swf文件。

会发现每个swf文件都是由几个swf拼接而成的,每一个cws就是一个swf文件。

而且在文件的开始会有一个{"totalPage":"210","fromPage":"  1","toPage":"  6"}字段。

这个可以当成Json也可以理解成AS3的对象。当然要想使用它,首先你需要对他进行序列化。  



totalPage  是说本文章的总页数。

fromPage  是从多少页来的。

toPage    是要到多少页去。

当然我们没有能力自己开发那样一个软件,那么就 使用 开源的flash2Print

请求的时候要考虑到用户的体验所以在服务端生成swf文件的时候,一般都会

选择拼页来实现。



那么请求第一页的时候,服务端发过来的数据是这样的,1-6页,为什么是1-6页呢,

因为万恶的中国的带宽。呵呵。那么第二页的数据就是2-7页。



那么对应的请求:



Page  id                 页码

   1                      1-6

   2                      2-7

   .                       .

   .                       .

   10                     6-15

那么这是一个非常简单的规律,因为要考虑用户的跳页所以我们要去用户发送页码的前四页

和后五页,这么做完全是为了是用户能更好的去体验并且减少服务端的压力。

那么后台调用并发送这些数据,我们在前端就 好办了。哈哈,写一个播放器就可以了.



那么首先我们要考虑一个问题就是, loader对就是loader,不能用常规的loader,因为返回的

的是2进制文件,所以我们不能用display包里的Loader去解析了.因为他不是正常的swf,原因是

这个2进制文件的开始还加了一个自定义对象需要我们去解析呢.



那么请问先生?你说不能用Loader对像,那你用什么呢?URLStream?URLLoader?,随你所好,用什么

都行。URLLoader最简单了。哈哈。你可以用。关于这些加2进制的方法其实也就是相当于把数据

进行提炼,然后让AVM认识你,这样就可以播放了。不过我记得那时候我做的时候写的非常愚蠢。哈哈。也没有怎么弄明白就提笔就写,结果效率大打折扣。源码如下:谢绝效尤,

不想到最后程序效率低的话你也可以这么写哈哈 。



package com.loader

{

    /**

     *      加载SWF文件 操作的 类 。

     *      提供一系列方法将拼接好的swf截取成byteArray类型数据然后

     *      分发给Ascode对象。

     */

    import com.display.DisplayLoader;

    import com.events.ItemLoadEvent;

    import com.events.SWFInfoComplelateEvent;

    import com.vo.pdfVO;

    import flash.events.EventDispatcher;

    public class SWFLoader extends EventDispatcher

    {

      

       import flash.display.Loader;

       import flash.display.Sprite;

       import flash.events.Event;

       import flash.net.URLRequest;

       import flash.net.URLStream;

       import flash.utils.ByteArray;

       import com.events.SWFInfoComplelateEvent;

       import com.vo.pdfVO;

       public function SWFLoader()

       {

           addEventListener(SWFInfoComplelateEvent.LOAD_COMPLELATE_DATES,onCompleteHandler);

       }

       /**

        *  加载完成

        *  然后用vo对象对其序列化

        *  

        */

       public var  vo:pdfVO;

       private function onCompleteHandler(e:SWFInfoComplelateEvent):void

       {

           

           e.target.removeEventListener(SWFInfoComplelateEvent.LOAD_COMPLELATE_DATES,onCompleteHandler);

             vo=new pdfVO(e.obj.parent);

           var leng:Number=e.obj.position.length-1;

           for(var i :int=0; i<leng;i++)

           {

              var byteArray:ByteArray=e.target.getStreamPostionDatas(e.obj.parent,e.obj.position.start,e.obj.position.end);

              var ds:DisplayLoader=new DisplayLoader(byteArray);

              boxes.push(ds);

              

           }

           if(boxes[0]!=null) this.dispatchEvent(new ItemLoadEvent(ItemLoadEvent.ITEM_OK,boxes));

           return;

       }

       /**

        *   加载方法

        *   

        */

       private var path:URLRequest;

       public function load(source:String):void

       {

              if(stream) close() ;

              stream=new URLStream();

              path=new URLRequest(source);

              try

              {

                  stream.load(path);

              }

              catch(e:Error)

              {

                  trace("error");

              }

              stream.addEventListener(Event.COMPLETE, completeHandler);

       }

           /**

            *   获得index位置上的DisplayLoader对象

           */

       private  var boxes:Array=;

       public function getDisplayyitemAt(index:int):DisplayLoader

       {

           if(boxes[index]==undefined) return null;

           return boxes[index];

       }

           /**

           *      流加载完成

           */

        private  var  swfInfoBox:Array=;

       private function completeHandler(e:Event):void

       {

               stream.removeEventListener(Event.COMPLETE, completeHandler);

              var arr:ByteArray=new ByteArray();

              stream.readBytes(arr,0,stream.bytesAvailable);

              var arrspeed:ByteArray=arr;

              swfInfoBox=SplitSWFInfo(arr);

              var obj:Object={

              stream:stream,

              parent:arr,

              alsoByte:arrspeed,

              position:swfInfoBox

              }

              var evt:SWFInfoComplelateEvent=new SWFInfoComplelateEvent("done",obj);

              this.dispatchEvent(evt);

       }         

       private var stream:URLStream;

       /**

        * 获得某一段数据

        */

       public function getStreamPostionDatas(source:ByteArray,index:Number,end:Number):ByteArray

       {

           var temp:ByteArray=new ByteArray();

           var j:Number=index;

           var length:Number=end-index;

           while(j<=end)

           {

                  temp[j-index]=source[j];

                  j++;

           }   

           return temp;

       }

       /**

        *  获得定点信息

        */

       public function getSWFpostionCollection(parent:ByteArray):Array

       {

           var swfInfoBox:Array=SplitSWFInfo(parent);

           return swfInfoBox;

       }

       /**

        *  截取swf信息(数据)

        *

        */

       public function  SplitSWFInfo(parent:ByteArray):Array

       {

           var leng:Number=parent.length;

           var endIndex:Array=;

           var startIndex:Array=;

           for(var i:Number=0;i<=leng;i++)

           {

              if(parent ==0x43&&parent[i+1]==0x57&&parent[i+2]==0x53)

              {

                  startIndex.push(i);

                  endIndex.push(i-1);

              }

           }

           var swfBox:Array=;

           var len:Number=startIndex.length;

           for(var j:int=0;j<=len;j++ )

           {   

              j==len-1?swfBox[j]={start:startIndex[j],end:leng}:

                         swfBox[j]={start:startIndex[j],end:endIndex[j+1]};   

           }

           return swfBox;

       }

       /**

        *  关闭方法

        */

       public function close():void

       {

           stream.close();

           stream=null;

       }

    }

}









其实不用那么写,费半天劲呵呵就是为了加载数据.当时可能是用flash  IDE写的.所以写的很乱.现在想想出力不讨好了.使用 URLLoader就 不一样了。省力多了,不过一定要注意设置

数据格式loader.dataFormat = URLLoaderDataFormat.BINARY;然后读经来以后,去找这个文件里有几个cws字符.然后分割swf数据.最后把分割后的数据放在一个数据集合或者

是一个大数组, 最后用一个Loader  去显示他们。
本页来自于www.ccflash.com,转摘麻烦说明下.

FLA  
Trackback

本文到目前为止有2条评论

  1. Gravatar Icon
    package com.display

    {

        /**

         *   显示DisplayLoader对象类

         *   基于Sprite类,显示avm1影片

         *

         */

        import flash.display.Loader;

        import flash.events.Event;

        import flash.utils.ByteArray;

        import flash.display.Sprite;

        import flash.net.URLRequest;

        import com.events.CreationDoneEvent;

        public class DisplayLoader extends  Sprite

        {

           /**

            *  构造函数

            *  @params   byteArray

            *  对截流的的byteArray对象用loader进行显示

            */

            private var dloader:Loader;

           public function DisplayLoader(byteArray:ByteArray)

           {

                  dloader=new Loader();

                  dloader.loadBytes(byteArray);

                  dloader.scaleX=0.5;

                  dloader.scaleY=0.5;

                  dloader.x=10;

                  dloader.y=60;

                  addChild(dloader);

           }

        }

    }



    当然 ,那时候用的是FlashIDE,相当厌恶。很多组建都是自己写的 。呵呵,UIscrollPane

    或者干脆自己写一个UIscrollPane,这样体积就下来了。

    之后,要考虑用户跳着看的好习惯。就是当我翻到 第1页的时候我去请求1-6页的原因。

    那么 如果是 顺顺序看的话,我应该在第5页鼠标第一次弹起的时候去请求下一个ID的数据,

    说实在的没啥难度。 然后如果他乱跳着看的话,那无所谓,他到哪页都会执行一个顺序,如果大数据集合里有这个数据就直接显示出来,如果没有的话就去按照前4后5的规则请求服务器

    其余的基本上就很简单了,仁者见仁智者见智了。简单说到这里。

    回复

  1. Gravatar Icon
    当然百度文库的后台,不是我们个人电脑所能比拟的,呵呵,没有服务器测试大家就做单机版吧。呵呵。拼的swf格式

    回复

添加评论