通过GZIP 对Web Service进行压缩
由于目前的GPRS网络带宽比较小,在进行移动应用开发的时候,可以考虑通过GZIP 对Web Service进行压缩.
下面是一个 虑通过GZIP 对Web Service进行压缩的SoapExtension例子.
using System;
using System.Text;
using System.IO;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
namespace WsClient
{
class ServerSoapExtension : SoapExtension
{
private Stream networkStream; //ChainStream原来的流
private Stream newStream; //ChainStream新建的流
public override object GetInitializer(Type serviceType)
{
//throw new Exception("GetInitializer() is not implemented.");
return null;
}
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
//throw new Exception("GetInitializer( ,) is not implemented.");
return null;
}
public override void Initialize(object initializer)
{
//throw new Exception("Initialize() is not implemented.");
}
//bool is_AfterSerialize = false;
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
AfterSerialize(message);
break;
case SoapMessageStage.BeforeDeserialize:
BeforeDeserialize(message);
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
/**********************************************************************************/
//对 Stream 的引用在任何 SoapMessageStage 之前传入 ChainStream 一次。
public override Stream ChainStream(Stream stream)
{
networkStream = stream;
newStream = new MemoryStream();
return newStream;
}
private void SaveStream(Stream stream, string filename)
{
stream.Position = 0;
FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.Flush();
copy(stream, fs);
sw.Close();
stream.Position = 0;
}
//序列化之后调用
public void AfterSerialize(SoapMessage message)
{
//压缩数据
Comp(message.Stream, networkStream);
}
//反序列化之前调用
public void BeforeDeserialize(SoapMessage message)
{
System.Diagnostics.Debug.Print("newStream:" + newStream.GetHashCode().ToString());
System.Diagnostics.Debug.Print("message.Stream:" + message.Stream.GetHashCode().ToString());
//解压数据
Decomp(networkStream, message.Stream);
}
//流复制
public void copy(Stream fromStream, Stream toStream)
{
StreamReader reader = new StreamReader(fromStream);
StreamWriter writer = new StreamWriter(toStream);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
//流解压
public void Decomp(Stream fromStream, Stream toStream)
{
//fromStream.Position = 0;
Stream s = new GZipInputStream(fromStream);
int size = 2048;
byte[] writeData = new byte[2048];
while (true)
{
size = s.Read(writeData, 0, size);
if (size > 0)
{
toStream.Write(writeData, 0, size);
}
else
{
break;
}
}
s.Close();
toStream.Position = 0;
}
//流压缩
public void Comp(Stream fromStream, Stream toStream)
{
Stream s = new GZipOutputStream(toStream);
byte[] writeData = new byte[fromStream.Length];
fromStream.Position = 0;
fromStream.Read(writeData, 0, (int)fromStream.Length);
s.Write(writeData, 0, writeData.Length);
s.Close();
}
private string ConverByteToString(byte[] buffer)
{
Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
int charlen = decoder.GetCharCount(buffer, 0, buffer.Length);
char[] chars = new char[charlen];
int Length = decoder.GetChars(buffer, 0, buffer.Length, chars, 0);
return new string(chars);
}
private byte[] ConvertStrToByte(string sourceStr)
{
Encoder defEncoder = Encoding.Default.GetEncoder();
int byteCount = defEncoder.GetByteCount(sourceStr.ToCharArray(), 0, sourceStr.Length, true);
byte[] bytes = new Byte[byteCount];
int bytesEncodedCount = defEncoder.GetBytes(sourceStr.ToCharArray(), 0, sourceStr.Length, bytes, 0, true);
return bytes;
}
}
[AttributeUsage(AttributeTargets.Method)]
public class ServerSoapExtensionAttribute : SoapExtensionAttribute
{
private int priority;
public override Type ExtensionType
{
get
{
return typeof(ServerSoapExtension);
}
}
public override int Priority
{
get
{
return priority;
}
set
{
priority = value;
}
}
}
}