本文是总结实际项目经验,代码不少是学习别人整合的,效果稳定可靠,有很大参考价值;但是也有不全面的地方,朋友们拿到可以按照自己需要修改。
场景是项目需要在客户端控制台软件和.NET MVC站点间互相传递数据,数据的量比较大,需要对数据进行转化为byte数据,再压缩后发送,接收方需要接收byte数据,再解压缩,还原成数据。
本文既有Web端发送接收数据,也有CS端发送接收数据,内容比较全面。
一、object和byte互转
object和byte互转是基础步骤,实现过程是很简单的,需要用到MemoryStream 、IFormatter 等类。
1、导入命名空间
using System.Collections.Generic;using System.IO;using System.Runtime.Serialization;usingSystem.Runtime.Serialization.Formatters.Binary;
2、object转byte方法
publicstaticbyte[] ToBytes(object obj)
{
if(obj ==null)returnnull;
byte[] buff;
using(MemoryStream ms =new MemoryStream())
{
IFormatter iFormatter =new BinaryFormatter();
iFormatter.Serialize(ms, obj);
buff = ms.GetBuffer();
}
return buff;
}
3. byte转object
publicstaticobjectToObject(byte[] bytes)
{
if(bytes ==null)returnnull;
object obj;
using(MemoryStream ms =new MemoryStream(bytes))
{
IFormatter iFormatter =new BinaryFormatter();
obj = iFormatter.Deserialize(ms);
}
return obj;
}
二、使用SharpZipLib进行GZip压缩和解压
经过反复实现修改,我感觉用开源类库ICSharpCode.SharpZipLib进行GZip压缩解压比.NET自带的System.IO.Compression.GZipStream效果更好。自己感觉,数据读取成DataTable压缩,不如把DataTable转化为实体类列表进行压缩效果好。
ICSharpCode.SharpZipLib你可以很容易从网络上获取到。
如果发送方对数据进行GZip压缩,接收方必须要对数据进行GZip解压。
1、导入命名空间
using ICSharpCode.SharpZipLib.GZip;usingSystem.IO;
2.GZip压缩
publicstaticbyte[] GZipCompress(byte[] data)
{
byte[] bytes =null;
using(MemoryStream o =new MemoryStream())
{
using(Stream s =new GZipOutputStream(o))
{
s.Write(data, 0, data.Length);
s.Flush();
}
bytes = o.ToArray();
}
return bytes;
}
3.GZip解压
privateconstintBUFFER_LENGTH =2048;
publicstaticbyte[] GZipDecompress(byte[] data)
{
byte[] bytes =null;
using(MemoryStream o =new MemoryStream())
{
using(MemoryStream ms =new MemoryStream(data))
{
using(Stream s =new GZipInputStream(ms))
{
s.Flush();
intsize =0;
byte[] buffer =newbyte[BUFFER_LENGTH];
while((size = s.Read(buffer,0, buffer.Length)) >0)
{
o.Write(buffer, 0, size);
}
}
}
bytes = o.ToArray();
}
return bytes;
}
三、Controller发送byte和控制台程序接收byte
1.Controller发送byte
在.NET MVC的Controller类中发送数据很简单,用Response进行如下发送就可以了,当然事先要把数据转化成byte,可以压缩也可以不压缩;但是这里的ContentType 内容表明这个数据是经过GZip压缩的。
privatevoidSendBytes(byte[] bytes)
{
Response.ClearContent();
Response.ContentType ="application/x-zip-compressed";//发送的是gzip格式 Response.BinaryWrite(bytes);
Response.End();
}
2.控制台程序接收byte
虽然说是Controller发送byte,其实是控制台程序访问了某个url后Controller才发送数据,因此这里用PostBinary首先进行访问。
publicstaticbyte[] PostBinary(stringurl,string body, CookieContainer cookie)
{
HttpWebRequest request = CreateRequest(url, body, cookie);
HttpWebResponse response = GetResponse(request);
byte[] bytes = ReadAllBytes(response);
return bytes;
}
privatestaticHttpWebRequest CreateRequest(stringurl,string body, CookieContainer cookie)
{
Encoding encoding = Encoding.UTF8;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method ="POST";
request.Accept ="text/html, application/xhtml+xml, */*";
request.ContentType ="application/x-www-form-urlencoded";
request.CookieContainer = cookie;
byte[] buffer = encoding.GetBytes(body);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
return request;
}
privatestatic HttpWebResponse GetResponse(HttpWebRequest request)
{
HttpWebResponse response =null;
try {
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = (HttpWebResponse)ex.Response;
}
return response;
}
ReadAllBytes方法要用到MemoryStream 类。
publicstaticbyte[] ReadAllBytes(HttpWebResponse response)
{
Stream responseStream = response.GetResponseStream();
intbufferSize =2048;
MemoryStream ms =new MemoryStream();
byte[] buffer =newbyte[bufferSize];
while(true)
{
intsize = responseStream.Read(buffer,0, bufferSize);
if(size ==0)break;
ms.Write(buffer, 0, size);
}
byte[] responseBytes = ms.ToArray();
return responseBytes;
}
四、控制台程序发送byte和Controller接收byte
这一部分和上一部分相反。控制台程序发送byte其实和向网站上传文件一样,Controller接收byte其实也和接收上传的文件一样。
1.控制台程序发送byte
这是是用HttpWebRequest给指定url上传文件,文件当然是按byte格式上传的。
publicstaticHttpWebResponse UploadBinary(stringurl,stringdataName,object obj)
{
byte[] dataBytes = ObjectBinaryHelper.Compress(obj);
if(dataBytes ==null) dataBytes =newbyte[] { };
stringboundary = DateTime.Now.Ticks.ToString("x");
HttpWebRequest uploadRequest = (HttpWebRequest)WebRequest.Create(url);//url为上传的地址uploadRequest.ContentType ="multipart/form-data; boundary="+ boundary;
uploadRequest.Method ="POST";
uploadRequest.Accept ="*/*";
uploadRequest.KeepAlive =true;
uploadRequest.Headers.Add("Accept-Language","zh-cn");
uploadRequest.Headers.Add("Accept-Encoding","gzip, deflate");
uploadRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
//uploadRequest.Headers["Cookie"] = cookie;//上传文件时需要的cookies
//创建一个内存流Stream memStream =new MemoryStream();
boundary ="--"+ boundary;
//添加上传文件参数格式边界stringparamFormat = boundary +"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}\r\n";
NameValueCollection param =new NameValueCollection();
param.Add("fname", dataName);//写上参数foreach(stringkeyin param.Keys)
{
stringformitem =string.Format(paramFormat, key, param[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
//添加上传文件数据格式边界stringdataFormat = boundary +"\r\nContent-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n";
stringheader =string.Format(dataFormat, dataName, dataName);byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
memStream.Write(dataBytes, 0, dataBytes.Length);
//添加文件结束边界byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("\r\n\n"+ boundary +"\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\nSubmit Query\r\n"+ boundary +"--");
memStream.Write(boundarybytes, 0, boundarybytes.Length);
//设置请求长度uploadRequest.ContentLength = memStream.Length;
//获取请求写入流Stream requestStream = uploadRequest.GetRequestStream();
//将内存流数据读取位置归零memStream.Position =0;
byte[] tempBuffer =newbyte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
//将内存流中的buffer写入到请求写入流requestStream.Write(tempBuffer,0, tempBuffer.Length);
requestStream.Close();
//获取到上传请求的响应HttpWebResponse response = GetResponse(uploadRequest);
return response;
}
2.Controller接收byte
Controller接收byte也等同于接收文件,这里的参数name是文件名称。
protectedbyte[] GetHttpBinary(string name)
{
if(this.Request.Files ==null||this.Request.Files.Count <=0)returnnull;
foreach(stringkeyinthis.Request.Files.Keys)
{
if(key == name)
{
HttpPostedFileBase httpPostedFile =this.Request.Files[key];
intfileContentLength = httpPostedFile.ContentLength;
byte[] fileBytes =newbyte[fileContentLength];
//创建Stream对象,并指向上传文件Stream fileStream = httpPostedFile.InputStream;
//从当前流中读取字节,读入字节数组中fileStream.Read(fileBytes,0, fileContentLength);
return fileBytes;
}
}
returnnull;
}