客户端程序传送图片到服务器

转载: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;
      }
  }
}

ImageWrapper

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

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

时间: 2025-01-18 18:13:02

客户端程序传送图片到服务器的相关文章

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

源码 (因为空间大小限制,不包含通信框架源码,通信框架源码请另行下载) 以前帮朋友做了一个图片采集系统,客户端采集相片后,通过TCP通信传送到服务器,本文把客户端传送图片到服务器的这部分提取出来. 由于每张图片的大小都不大,所以我们在传输图片时,没有采用传送文件的方式,而是采用了直接序列化图片的方式来进行. 当前支持的图片类型: jpg,png,gif 您可以自己添加扩充支持的图片类型 通信框架采用英国的开源的networkcomms2.3.1 通信框架   序列化器采用开源的protobuf.

php编写tcp服务器和客户端程序

这是我从别的地方看到的. 1.修改php.ini,打开extension=php_sockets.dll 2.客户端程序 SocketClient.php <?php set_time_limit(0); $host = "127.0.0.1"; $port = 3046; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socket\n"); $co

Excel服务器待办事宜提醒客户端程序 [2014.03.19 日更新]

软件可以免费使用,作者仅保留一个版权声明于待办事宜提醒的状态栏处. 适用版本:Excel服务器9.2版及以上版本均支持. 欢迎大家提意见!联系QQ:303629685[Excel服务器待办事宜提醒客户端程序 20140113更新]        1.修复查询语句的小错误.        2.服务器端设置后,自动带出已设置的服务器端除密码外的相关信息.        3.客户端提醒设置后,自动带出已设置的客户端除密码外的相关信息.[Excel服务器待办事宜提醒客户端程序 20140109更新] 

c++下基于windows socket的单线程服务器客户端程序

今天自己用编写了一个简单的c++服务器客户端程序,注释较详细,在此做个笔记. windows下socket编程的主要流程可概括如下:初始化ws2_32.dll动态库-->创建套接字-->绑定地址信息-->服务器进行监听/客户端连接服务器-->数据交换-->关闭套接字对象. 服务器端: 1 #include <Winsock2.h> 2 #include <Ws2tcpip.h> 3 #include <iostream> 4 5 #prag

基于XMPP的IOS聊天客户端程序(XMPP服务器架构)

最近看了关于XMPP的框架,以文本聊天为例,需要发送的消息为: <message type="chat" from="[email protected]" to="[email protected]">          <body>helloWord</body>      </message> 基中from是从哪个用户发送的消息,to是发给谁的消息,XMPP的用户都是以邮箱形式.body就是我们

黑马程序员 【】java学习之路——TCP(三)客户端上传文件到服务器

------- <a href="http://www.itheima.com" target="blank">android培训</a>.<a href="http://www.itheima.com" target="blank">java培训</a>.期待与您交流! ---------- import java.io.*; import java.net.*; class

Python Socket基础学习,注意,需要先开服务器程序,在开客户端程序,

服务器端 # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from socket import * from time import * HOST='' PORT=1122#侦听端口 BUFSIZ=1024 ADDR=(HOST,PORT) sock=socket(AF_INET,SOCK_STREAM) sock.bind(ADDR) sock.listen(5) #条件 STOP_CHAT=False whi

php编写TCP服务端和客户端程序

From: http://blog.csdn.net/anda0109/article/details/46655301 1.修改php.ini,打开extension=php_sockets.dll 2.服务端程序SocketServer.php [php] view plaincopyprint? <?php //确保在连接客户端时不会超时 set_time_limit(0); //设置IP和端口号 $address = "127.0.0.1"; $port = 3046;

简单的客户端程序

今天, 我在写控制小车的上位机程序, 要发送指令给小车的wifi模块,  所以我需要编写客户端程序, 因为wifi模块已配置成了服务器. 客户端要连接服务器, 需要知道服务器的IP地址, 不是它的IPV4的地址, 而是它的默认路由IP, 然后是指定端口号.   IP确定同一网络下的主机位置, 端口号确定主机上我要通信的进程. 知道了关键部分(原理),接下来就是怎么编程了. *****************************************  图解 ****************