zoukankan      html  css  js  c++  java
  • 客户端程序传送图片到服务器

    转载:http://www.cnblogs.com/networkcomms/p/4314898.html

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

    以前帮朋友做了一个图片采集系统,客户端采集相片后,通过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;
          }
      }
    }
    复制代码
    复制代码

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

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

  • 相关阅读:
    TCP Socket 粘包
    Toast连续弹出的问题
    SDK Build Tools revision (19.0.3) is too low for project Minimum required is 19.1.0
    数据结构精要------直接选择和堆排序算法
    hdoj 2199 Can you solve this equation? 【二分枚举】
    云端数据遭觊觎 安全问题不容忽视
    leetcode || 58、Length of Last Word
    【安全加密技术】非对称加密
    无处不在的微创新——验证码的故事
    IDLE经常使用快捷键汇总
  • 原文地址:https://www.cnblogs.com/Jeely/p/10972052.html
Copyright © 2011-2022 走看看