Flex与后台传输解压缩大数据量

本文BlazeDS技术连接flex和java端,以Remote Object方式传输数据为例,
一、Java端返回数据压缩并在前台解压:
首先建一个类ROResult.java来包装返回的result,如下:
import java.io.Serializable;

public class ROResult implements Serializable {

    private static final long serialVersionUID = -6410217400836125781L;
    private Object result;
   
    public ROResult(){
    }
    
    public ROResult(Object res){
        result = res;
    }
}

再建立一个压缩后的二进制存放类CompressedResult.java:
import java.io.Serializable;

public class CompressedResult  implements Serializable{

	private static final long serialVersionUID = 3697351121688911929L;	
	
	byte[] data;

	public byte[] getData() {
		return data;
	}

	public void setData(byte[] data) {
		this.data = data;
	}
	
	public CompressedResult(byte[] data){
		setData(data);
	}
	
	public CompressedResult(){
	}

}

以上两个类也需要在前台也建立对应的VO:
ROResult.as:
	[RemoteClass(alias="com.model.ROResult")]
	public class ROResult {
		public var result:Object;
	}

CompressedResult.as:
	import flash.utils.ByteArray;
	
	[RemoteClass(alias="com.model.CompressedResult")]
	public class CompressedResult
	{
		public function CompressedResult()
		{
		}
		public var data:ByteArray;		

	}


后台调用压缩方法:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;

	/**
	 * Try Compress ROResult<br/>
	 * Result will auto-decompressed by BaseCommand on client side.
	 * @param result result to compress
	 * @return true if compressed
	 */
	public static boolean tryCompressROResult(ROResult result){
		if(result==null)return false;
		
		Object ret=result.getResult();
		if(ret==null){//do not compress null
			return false;
		}
		
		byte[] arr=compressAmf(ret);
		
		if(arr!=null){//compress succeeded!
			result.setResult(new CompressedResult(arr));
			return true;
		}
		return false;
	}
	
	public static final int DEFAULTCOMPRESSINGTHRESHOLD=1024;
	public static byte[] compressAmf(Object obj){
		return compressAmf(obj,DEFAULTCOMPRESSINGTHRESHOLD);		
	}
	public static byte[] compressAmf(Object obj,int threshold){
		if(obj==null)return null;
		try{
			ByteArrayOutputStream bout = new ByteArrayOutputStream();
			
	    	SerializationContext context = new SerializationContext();
		    Amf3Output amf3Output = new Amf3Output(context);
		    amf3Output.setOutputStream(bout);		    
			amf3Output.writeObject(obj);			
		    amf3Output.flush();
		    amf3Output.close();
		    
		    int bufLen=bout.size();				    
		    //binary data less than threshold
		    if(bufLen<=threshold){
		    	return null;
		    }
		    byte[] buf=bout.toByteArray();
		    
		    java.util.zip.Deflater  df=
		    	new java.util.zip.Deflater(java.util.zip.Deflater.BEST_COMPRESSION,true);
		    df.setInput(buf);
		    df.finish();
		    
		    //reuse buffer
		    bout.reset();
		    byte[] deflatered=new byte[bufLen];		    
		    while(!df.finished()){		    	
		    	int len=df.deflate(deflatered);
		    	if(len>0){
		    		bout.write(deflatered,0,len);
		    	}
		    }
		    return bout.toByteArray();
		}catch(Exception e){
			return null;
		}
}
	

该方法将result压缩成二进制并转化成CompressedResult类,存入ROResult中。
而前台需要在flex command中解压,如下解压方法:
	import flash.errors.IOError;
	import flash.utils.ByteArray;
         /**
         * Try Decompress ROResult<br/>
         * Use with tryCompressROResult on server side
         * @return true if content is decompressed
         */
         public static function tryDecompressROResult(result:ROResult):Boolean{
         	if(result==null)return false;
         	var ret:Object=result.result;
         	if(ret==null)return false;
         	if(ret is CompressedResult){
         		ret=decompressAmf((ret as CompressedResult).data);
         		if(ret!=null){
         			result.result=ret;
         			return true;
         		}
         	}
         	return false;
         }
         public static function decompressAmf(data:ByteArray):Object{
         	if(data==null)return null;
			try{
				if(data is ByteArray){					
					var b:ByteArray=data as ByteArray;		
					var compressedLength:int=b.length;
					
					var infStartTime:Number=new Date().getTime();
					b.inflate();
					
					var infEndTime:Number=new Date().getTime();
					trace("Compressing rate:"+(Number(compressedLength)/b.length));
					trace("Decompress time cost:"+(infEndTime-infStartTime));					
										
					var ret:Object = b.readObject();
					
					var readEndTime:Number=new Date().getTime();					
					trace("ReadObject time cost:"+(readEndTime-infEndTime));
					return ret;
				}
			}catch(ex:IOError){
				var errInfo:String="IOError during decompressing: "+ex;
				trace(errInfo);
				throw new Error(errInfo);
			}
			return null;
         }

二、Flex端压缩数据并传输到后台解压:
前台压缩方法:
	import flash.utils.ByteArray;
	
	import mx.utils.Base64Decoder;
	import mx.utils.Base64Encoder;
		/**
		 * WARNING:CONTENT COMPRESSED
		 **/
      	public static function serializeToString(value:Object):String{  
             if(value==null){  
                 throw new Error("null isn't a legal serialization candidate");  
             }  
             var bytes:ByteArray = new ByteArray();  
             bytes.writeObject(value);  
             bytes.position = 0;  
             //compress content
             bytes.deflate();
             var be:Base64Encoder = new Base64Encoder();  
             be.encodeBytes(bytes);  
             var res:String = be.toString();  
             be.reset();
             return res;  
         }

该方法将数据压缩成字符串string类型。

后台解压方法:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;
import flex.messaging.util.Base64;

	/**
	 * Read Object from base64 string to object<br/>
	 * WARNING: COMPRESSED!!
	 * @param <T>
	 * @param amf
	 * @param classType
	 * @return
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T fromAmf(final String amf, Class<T> classType) throws ClassNotFoundException, IOException {
	    return (T) fromAmf(amf);
	}

	public static Object fromAmf(final String amf) throws IOException, ClassNotFoundException {
		SerializationContext context = new SerializationContext();
	    final Base64.Decoder decoder = new Base64.Decoder();
	    decoder.decode(amf);
	    byte[] input = decoder.flush();
	    decoder.reset();
	    
	    //buffer should be compressed!!
	    input= uncompress(new ByteArrayInputStream(input));
	    
	    InputStream bIn = new ByteArrayInputStream(input);
	    Amf3Input amf3Input = new Amf3Input(context);
	    amf3Input.setInputStream(bIn);
	    return amf3Input.readObject();
	}
	
	
	private static byte[] uncompress(InputStream is) throws IOException{
		java.util.zip.InflaterInputStream  infS=new java.util.zip.InflaterInputStream(
				is,
				new java.util.zip.Inflater(true)
				);
		ByteArrayOutputStream tmp=new ByteArrayOutputStream();
		byte[] buf=new byte[1024];
		for(;;){
			int len=-1;
			try {
				len = infS.read(buf);
			} catch(EOFException eofe){	
				break;
			}catch (IOException e) {
				throw e;
			}
			if(len==-1){
				break;
			}
			tmp.write(buf,0,len);
		}
		return tmp.toByteArray();
	}


该解压接口fromAmf(final String amf, Class<T> classType)两个参数,分别是前台压缩的字符串和解压后的类型。调用例子:List requestIdList = (List)fromAmf(idListString,List.class);

你可能感兴趣的:(解压缩数据,Flex 与后台传输)