本文是总结实际项目经验, 代码不少是学习别人整合的, 效果稳定可靠, 有很大参考价值; 但是也有不全面的地方, 朋友们拿到可以按照自己需要修改.
场景是项目需要在客户端控制台软件和. NET MVC 站点间互相传递数据, 数据的量比较大, 需要对数据进行转化为 byte 数据, 再压缩后发送, 接收方需要接收 byte 数据, 再解压缩, 还原成数据.
本文既有 web 端发送接收数据, 也有 CS 端发送接收数据, 内容比较全面.
一, object 和 byte 互转
object 和 byte 互转是基础步骤, 实现过程是很简单的, 需要用到 MemoryStream,IFormatter 等类.
1, 导入命名空间
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
2,object 转 byte 方法
- public static byte[] ToBytes(object obj)
- {
- if (obj == null) return null;
- byte[] buff;
- using (MemoryStream ms = new MemoryStream())
- {
- IFormatter iFormatter = new BinaryFormatter();
- iFormatter.Serialize(ms, obj);
- buff = ms.GetBuffer();
- }
- return buff;
- }
3. byte 转 object
- public static object ToObject(byte[] bytes)
- {
- if (bytes == null) return null;
- 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;
- using System.IO;
2.GZip 压缩
- public static byte[] 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 解压
- private const int BUFFER_LENGTH = 2048;
- public static byte[] 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();
- int size = 0;
- byte[] buffer = new byte[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 压缩的.
- private void SendBytes(byte[] bytes)
- {
- Response.ClearContent();
- Response.ContentType = "application/x-zip-compressed";// 发送的是 gzip 格式
- Response.BinaryWrite(bytes);
- Response.End();
- }
2. 控制台程序接收 byte
虽然说是 Controller 发送 byte, 其实是控制台程序访问了某个 url 后 Controller 才发送数据, 因此这里用 PostBinary 首先进行访问.
- public static byte[] PostBinary(string url, string body, CookieContainer cookie)
- {
- HttpWebRequest request = CreateRequest(url, body, cookie);
- HttpWebResponse response = GetResponse(request);
- byte[] bytes = ReadAllBytes(response);
- return bytes;
- }
- private static HttpWebRequest CreateRequest(string url, 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;
- }
- private static HttpWebResponse GetResponse(HttpWebRequest request)
- {
- HttpWebResponse response = null;
- try
- {
- response = (HttpWebResponse)request.GetResponse();
- }
- catch (WebException ex)
- {
- response = (HttpWebResponse)ex.Response;
- }
- return response;
- }
ReadAllBytes 方法要用到 MemoryStream 类.
- public static byte[] ReadAllBytes(HttpWebResponse response)
- {
- Stream responseStream = response.GetResponseStream();
- int bufferSize = 2048;
- MemoryStream ms = new MemoryStream();
- byte[] buffer = new byte[bufferSize];
- while (true)
- {
- int size = 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 格式上传的.
- public static HttpWebResponse UploadBinary(string url, string dataName, object obj)
- {
- byte[] dataBytes = ObjectBinaryHelper.Compress(obj);
- if (dataBytes == null) dataBytes = new byte[] { };
- string boundary = 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;
- // 添加上传文件参数格式边界
- string paramFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}\r\n";
- NameValueCollection param = new NameValueCollection();
- param.Add("fname", dataName);// 写上参数
- foreach (string key in param.Keys)
- {
- string formitem = string.Format(paramFormat, key, param[key]);
- byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
- memStream.Write(formitembytes, 0, formitembytes.Length);
- }
- // 添加上传文件数据格式边界
- string dataFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n";
- string header = 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 = new byte[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 是文件名称.
- protected byte[] GetHttpBinary(string name)
- {
- if (this.Request.Files == null || this.Request.Files.Count <= 0) return null;
- foreach (string key in this.Request.Files.Keys)
- {
- if (key == name)
- {
- HttpPostedFileBase httpPostedFile = this.Request.Files[key];
- int fileContentLength = httpPostedFile.ContentLength;
- byte[] fileBytes = new byte[fileContentLength];
- // 创建 Stream 对象, 并指向上传文件
- Stream fileStream = httpPostedFile.InputStream;
- // 从当前流中读取字节, 读入字节数组中
- fileStream.Read(fileBytes, 0, fileContentLength);
- return fileBytes;
- }
- }
- return null;
- }
来源: https://www.cnblogs.com/tkt2016/p/12167197.html