百度文库的关键技术
百度文库的关键技术在于两方面,一是文档的flash转换,这一步可以用flashpaper实现,关键是如果将flashpaer分割为适合互联网快速下载的小flash文档,这一步现在基本已经没问题了;第二步 就是阅读器的开发,当然如果对flash结构熟悉的话 可以直接引用baidu文库的阅读器 改改就行。以上两个关键问题解决了 你就能做出一个完美的“百度文库“了,到目前为止,我对第一步可以说是没问题,但我对flash结构不是很熟悉,所以想和对flash结构熟悉的人合作开发,共创辉煌。
最近上网总是有人问我百度文库技术或者是flex paper技术。呵呵。其实这个东西没有想的那么难。就百度文库来说,可以证明无论是adobe的 flash paper还是开源 的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 isplayLoader=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) isplayLoader
{
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 去显示他们。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wkyb608/archive/2010/11/23/6028968.aspx
还有一网上朋友的答案:
百度reader加载swf文档的代码,结果发现百度是把文档的每一页都进行了打印,然后每5页或者10进行组合,在头部添加一些需要的参数,以cws和FWS和版本号进行从数据流中分割出每一页的stream,然后进行加载显示。reader阅读器其实也很简单,按页数生成一些空白页 这也空白页也就是显示加载swf的容器。
文档转换时应用程序转换的,自己用c#写的,实现了office web txt等到pdf再到swf的转换,并提取画面最丰富的一页打印成图片,作为网页表现用,解决了pdf转换乱码的问题。提取了文档中的文字内容,针对搜索引擎进行输出,提高搜索引擎的收录。
实现了web的表现,client端的阅读器是用百度的哈,我没有自己开发。加载是按客户端请求的5或10页进行组合的。
阿里云: www.aliyun.com
华赐软件: www.huacisoft.com
C#开源社区: www.opencsharp.net
清泓美肤苑: 清泓美肤苑
bootstrap权限管理系统: Asp.Net Mvc3 bootstrap权限管理系统