Sep
1
百度文库应用 沈龙七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,转摘麻烦说明下.
Trackback
本文到目前为止有2条评论
-
当然百度文库的后台,不是我们个人电脑所能比拟的,呵呵,没有服务器测试大家就做单机版吧。呵呵。拼的swf格式
{
/**
* 显示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的规则请求服务器
其余的基本上就很简单了,仁者见仁智者见智了。简单说到这里。
回复