客戶端程序傳送圖片到服務器


轉載: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以上,最好以傳送文件的形式,分段發送.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM