当前位置: 代码迷 >> C# >> [c#源码分享]客户端程序传递图片到服务器
  详细解决方案

[c#源码分享]客户端程序传递图片到服务器

热度:34   发布时间:2016-05-05 04:46:40.0
[c#源码分享]客户端程序传送图片到服务器

源码  (因为空间大小限制,不包含通信框架源码,通信框架源码请另行下载)

以前帮朋友做了一个图片采集系统,客户端采集相片后,通过TCP通信传送到服务器,本文把客户端传送图片到服务器的这部分提取出来。

由于每张图片的大小都不大,所以我们在传输图片时,没有采用传送文件的方式,而是采用了直接序列化图片的方式来进行。

当前支持的图片类型: jpg,png,gif 您可以自己添加扩充支持的图片类型

通信框架采用英国的开源的networkcomms2.3.1 通信框架   序列化器采用开源的protobuf.net

 

我们先开看一下实现的效果

服务器端:

客户端:

在服务器端,我们把收到的图片保存在D盘根目录下(您可以另外指定路径),打开D盘看到收到的图片如下:

下面看一下具体的过程

第一步,首先进行服务器端的设置

  (1)监听端口:

    

     IPEndPoint thePoint = new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text));               TCPConnection.StartListening(thePoint, false);            button1.Text = "监听中";            button1.Enabled = false;

(2) 针对图片上传写对应的处理方法:

 NetworkComms.AppendGlobalIncomingPacketHandler<ImageWrapper>("UploadImage", IncomingUploadImage);
  //处理客户端发来的图片        private void IncomingUploadImage(PacketHeader header, Connection connection, ImageWrapper wrapper)        {            try            {                //具体的解析工作由通信框架完成                //从图片包装器中获取到图片文件和图片名称                Image image = wrapper.Image;                string fileName = wrapper.ImageName;                             //获取文件扩展名                int index = fileName.LastIndexOf('.');                string extion = fileName.Substring(                    index + 1, fileName.Length - index - 1);                extion = extion.ToLower();                //设置文件格式                ImageFormat imageFormat = ImageFormat.Bmp;                switch (extion)                {                    case "jpg":                    case "jpeg":                        imageFormat = ImageFormat.Jpeg;                        break;                    case "png":                        imageFormat = ImageFormat.Png;                        break;                    case "gif":                        imageFormat = ImageFormat.Gif;                        break;                }
//此处,我们手工指定了一个保存路径,您可以自定义 image.Save(
@"D:\" + fileName, imageFormat); ResMsgContract contract = new ResMsgContract(); contract.Message = "上传成功"; //发送回复信息给客户端 connection.SendObject("ResUploadImage", contract); } catch (Exception ex) { } }

第二步:客户端的设置

(1)连接服务器:

  

 //给连接信息对象赋值            connInfo = new ConnectionInfo(txtIP.Text, int.Parse(txtPort.Text));            //如果不成功,会弹出异常信息            newTcpConnection = TCPConnection.GetConnection(connInfo);            TCPConnection.StartListening(connInfo.LocalEndPoint);            button1.Enabled = false;            button1.Text = "连接成功";

(2)从本地选择图片并上传

  openFileDialog1.Filter = "图片文件|*.jpg|所有文件|*.*";            if (openFileDialog1.ShowDialog() == DialogResult.OK)            {                string shortFileName = System.IO.Path.GetFileName(openFileDialog1.FileName);                                  //图片包装类                ImageWrapper wrapper = new ImageWrapper(shortFileName, Image.FromFile(openFileDialog1.FileName));                //发送图片包装类到服务器,并获取返回信息                ResMsgContract resMessage = newTcpConnection.SendReceiveObject<ResMsgContract>("UploadImage", "ResUploadImage", 8000, wrapper);                if (resMessage.Message == "上传成功")                {                    MessageBox.Show("图片已经上传到服务器");                }                else                {                    MessageBox.Show("图片没有发送成功");                }            }       

(三)关于 ImageWrapper类

在客户端与服务器端通信的过程中,我们注意到上面的程序中使用了一个ImageWrapper类,用来传递图片(Image)对象。

 ImageWrapper类,存放在MessageContract类库中,此类用来序列化图片

我们知道Image类并不直接支持序列化,所以我们采用的方式是序列化之前把Image转化为二级制数据,反序列化之前再把二级制数据转化为Image类。

我们只负责定义ImageWrapper类,其他工作通信框架帮我们做好了。

  using System;using System.Collections.Generic;using System.Text;using ProtoBuf;using System.Drawing;using System.IO;using ProtoBuf;namespace MessageContract{    [ProtoContract]   public class ImageWrapper  {      /// <summary>      /// 把Image对象存储为私有的字节数组      /// </summary>      [ProtoMember(1)]      private byte[] _imageData;         /// <summary>      /// 图片名称      /// </summary>      [ProtoMember(2)]      public string ImageName { get; set; }         /// <summary>       /// 图片对象      /// </summary>      public Image Image { get; set; }         /// <summary>      /// 私有的无参数构造函数 反序列化时需要使用      /// </summary>      private ImageWrapper() { }         /// <summary>      /// 创建一个新的 ImageWrapper类      /// </summary>      /// <param name="imageName"></param>      /// <param name="image"></param>      public ImageWrapper(string imageName, Image image)      {          this.ImageName = imageName;          this.Image = image;      }         /// <summary>      ///序列化之前,把图片转化为二进制数据      /// </summary>      [ProtoBeforeSerialization]      private void Serialize()      {          if (Image != null)          {              //We need to decide how to convert our image to its raw binary form here              using (MemoryStream inputStream = new MemoryStream())              {                  //For basic image types the features are part of the .net framework                  Image.Save(inputStream, Image.RawFormat);                     //If we wanted to include additional data processing here                  //such as compression, encryption etc we can still use the features provided by NetworkComms.Net                  //e.g. see DPSManager.GetDataProcessor<LZMACompressor>()                     //Store the binary image data as bytes[]                  _imageData = inputStream.ToArray();              }          }      }         /// <summary>      /// 反序列化时,把二进制数据转化为图片对象      /// </summary>      [ProtoAfterDeserialization]      private void Deserialize()      {          MemoryStream ms = new MemoryStream(_imageData);             //If we added custom data processes we have the perform the reverse operations here before           //trying to recreate the image object          //e.g. DPSManager.GetDataProcessor<LZMACompressor>()             Image = Image.FromStream(ms);          _imageData = null;      }  }}
ImageWrapper

工作到此完成,很少的代码量,就帮我们实现了传递客户端图片保存在服务器的功能。

注意:此种方式并不适合传递比较大的图片,如果图片比较大,比如10M以上,最好以传送文件的形式,分段发送.

 

  相关解决方案