天天看點

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:

大家晚上好:

本期我們接着上次講即時通訊服務端外加用戶端檔案傳輸

服務端

1.服務端的作用:

我們在通信時不可能一對一直接連接配接到千裡之外的另外一台手機
           

有衆多原因 其一是: ip 不在同一網段,其二:每個手機地域限制影響

包括大家衆所周知的QQ,微信 等 都是 通過 中轉站 伺服器(監聽端程式)

伺服器所處環境在公網,用戶端可以直接通過公網IP連接配接,

2.用戶端與用戶端通訊:

新增賬號是生成唯一ID,用作每個用戶端的key 存儲在服務端,用戶端連接配接服務端後将key用作連接配接對象的key 存儲在緩存中,

例如: 有兩個用戶端 A,B,一個服務端C

A發消息給B,

首先是擷取服務端所存儲的所有連接配接對象資訊包括Key,加載到A本地

A指定B對象得到key 發送資訊給服務端;

服務端C接收到資訊 解析接收人的key ,在連接配接對象記憶體中去key的連接配接對象

把消息發送給B。

也就是上篇文章畫的草圖 :

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:

下面展示服務端程式:

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:

##下面是服務端代碼

下面介紹下檔案傳輸思路:

用戶端把檔案發送給服務端:服務端儲存至IIS站點下:

将路徑傳回給接收消息的一端:

例如下面這張圖檔:就是測試所作的

前面的ip 是我個人的伺服器公網位址

http://47.115.26.219:8099/mmexport1631624696079.jpg

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using Newtonsoft.Json;

namespace ChatServer
{
    public partial class FServer : Form
    {
        public FServer()
        {
            InitializeComponent();
            //關閉對文本框的非法線程操作檢查
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        //分别建立一個監聽用戶端的線程和套接字
        Thread threadWatch = null;
        Socket socketWatch = null;

        public const int SendBufferSize = 2 * 1024;
        public const int ReceiveBufferSize = 8 * 1024;

        private void btnStartService_Click(object sender, EventArgs e)
        {
            //定義一個套接字用于監聽用戶端發來的資訊  包含3個參數(IP4尋址協定,流式連接配接,TCP協定)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //發送資訊 需要1個IP位址和端口号
            //擷取服務端IPv4位址
            IPAddress ipAddress = Dns.GetHostAddresses(Dns.GetHostName())[5];// GetLocalIPv4Address();
            lblIP.Text = ipAddress.ToString();
            //給服務端賦予一個端口号
            int port = 9000;
            lblPort.Text = port.ToString();

            //将IP位址和端口号綁定到網絡節點endpoint上 
            IPEndPoint endpoint = new IPEndPoint(ipAddress, port);
            //将負責監聽的套接字綁定網絡端點
            socketWatch.Bind(endpoint);
            //将套接字的監聽隊列長度設定為20
            socketWatch.Listen(20);
            //建立一個負責監聽用戶端的線程 
            threadWatch = new Thread(WatchConnecting);
            //将窗體線程設定為與背景同步
            threadWatch.IsBackground = true;
            //啟動線程
            threadWatch.Start();
            txtMsg.AppendText("伺服器已經啟動,開始監聽用戶端傳來的資訊!" + "\r\n");
            btnStartService.Enabled = false;
        }

        /// <summary>
        /// 擷取本地IPv4位址
        /// </summary>
        /// <returns>本地IPv4位址</returns>
        public IPAddress GetLocalIPv4Address()
        {
            IPAddress localIPv4 = null;
            //擷取本機所有的IP位址清單
            IPAddress[] ipAddressList = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress ipAddress in ipAddressList)
            {
                //判斷是否是IPv4位址
                if (ipAddress.AddressFamily == AddressFamily.InterNetwork) //AddressFamily.InterNetwork表示IPv4 
                {
                    localIPv4 = ipAddress;
                    break;
                }
                else
                    continue;
            }
            return localIPv4;
        }

        //用于儲存所有通信用戶端的Socket
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

        //建立與用戶端建立連接配接的套接字
        Socket socConnection = null;
        string clientName = null; //建立通路用戶端的名字
        IPAddress clientIP; //通路用戶端的IP
        int clientPort; //通路用戶端的端口号
        /// <summary>
        /// 持續不斷監聽用戶端發來的請求, 用于不斷擷取用戶端發送過來的連續資料資訊
        /// </summary>
        private void WatchConnecting()
        {
            while (true)
            {
                try
                {
                    socConnection = socketWatch.Accept();
                }
                catch (Exception ex)
                {
                    txtMsg.AppendText(ex.Message); //提示套接字監聽異常
                    break;
                }
                //擷取通路用戶端的IP
                clientIP = (socConnection.RemoteEndPoint as IPEndPoint).Address;
                //擷取通路用戶端的Port
                clientPort = (socConnection.RemoteEndPoint as IPEndPoint).Port;
                //建立通路用戶端的唯一辨別 由IP和端口号組成 
                clientName = "IP: " + clientIP + " Port: " + clientPort;
                lstClients.Items.Add(clientName); //在用戶端清單添加該通路用戶端的唯一辨別
                dicSocket.Add(clientName, socConnection); //将用戶端名字和套接字添加到添加到資料字典中


                //建立通信線程 
                ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg);
                Thread thread = new Thread(pts);
                thread.IsBackground = true;
                //啟動線程
                thread.Start(socConnection);
                txtMsg.AppendText("IP: " + clientIP + " Port: " + clientPort + " 的用戶端與您連接配接成功,現在你們可以開始通信了...\r\n");
            }
        }

        /// <summary>
        /// 發送資訊到用戶端的方法
        /// </summary>
        /// <param name="sendMsg">發送的字元串資訊</param>
        private void ServerSendMsg(string sendMsg)
        {
            sendMsg = txtSendMsg.Text.Trim();
            //将輸入的字元串轉換成 機器可以識别的位元組數組
            byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //向用戶端清單選中的用戶端發送資訊
            if (!string.IsNullOrEmpty(lstClients.Text.Trim()))
            {
                //獲得相應的套接字 并将位元組數組資訊發送出去
                dicSocket[lstClients.Text.Trim()].Send(arrSendMsg);
                //通過Socket的send方法将位元組數組發送出去
                txtMsg.AppendText("您在 " + GetCurrentTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的用戶端發送了:\r\n" + sendMsg + "\r\n");
            }
            else //如果未選擇任何用戶端 則預設為群發資訊
            {
                //周遊所有的用戶端
                for (int i = 0; i < lstClients.Items.Count; i++)
                {
                    dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg);
                }
                txtMsg.AppendText("您在 " + GetCurrentTime() + " 群發了資訊:\r\n" + sendMsg + " \r\n");
            }
        }

        string strSRecMsg = null;
        public ScokeSendFile sendFile = null;
        public bool IsHead = false;
        public string ReceiveUserID { get; set; }

        public string SendClientMsg { get; set; }
        /// <summary>
        /// 接收用戶端發來的資訊
        /// </summary>
        private void ServerRecMsg(object socketClientPara)
        {
            Socket socketServer = socketClientPara as Socket;

            long fileLength = 0;
            while (true)
            {
                int firstReceived = 0;
                byte[] buffer = new byte[ReceiveBufferSize];
                try
                {
                    //擷取接收的資料,并存入記憶體緩沖區  傳回一個位元組數組的長度
                    if (socketServer != null) firstReceived = socketServer.Receive(buffer);

                    if (firstReceived > 0) //接受到的長度大于0 說明有資訊或檔案傳來
                    {
                        if (buffer[0] == 0) //0為文字資訊
                        {
                            strSRecMsg = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);//真實有用的文本資訊要比接收到的少1(辨別符)
                            var Mymsg = strSRecMsg.Split('#');
                            if (Mymsg[0] == "000200030006")
                            {
                                MessageBox box = JsonConvert.DeserializeObject<MessageBox>(Mymsg[1]);
                                string sendMsg = "000200030006*" + Mymsg[1];

                                //byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                                ClientSendMsg(dicSocket.Where(x => x.Key.Contains(box.RID)).FirstOrDefault().Key, sendMsg,0);
                                //dicSocket.Where(x => x.Key.Contains(box.RID)).FirstOrDefault().Value.Send(arrSendMsg);
                                //獲得相應的套接字 并将位元組數組資訊發送出去
                                // dicSocket[lstClients.Text.Trim()].Send(arrSendMsg);


                            }

                            txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n");
                        }
                        if (buffer[0] == 2)//2為檔案名字和長度
                        {
                            string fileNameWithLength = "";
                            try
                            {
                                fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);
                                if (!fileNameWithLength.Contains("Head#"))
                                {
                                    IsHead = false;
                                    sendFile = JsonConvert.DeserializeObject<ScokeSendFile>(fileNameWithLength);

                                    strSRecMsg = sendFile.FileNames.Split('-').First(); //檔案名
                                    fileLength = Convert.ToInt64(sendFile.FileNames.Split('-').Last());//檔案長度

                                    ScokeSendFile ClientFile= JsonConvert.DeserializeObject<ScokeSendFile>(fileNameWithLength);
                                    ClientFile.FilePath= [email protected]"http://47.115.26.219:8099/{strSRecMsg}";
                                      SendClientMsg = JsonConvert.SerializeObject(ClientFile);
                                    ReceiveUserID = dicSocket.Where(x => x.Key.Contains(sendFile.ReceiveUserID)).FirstOrDefault().Key;
                                  
                                }
                                else
                                {
                                    IsHead = true;
                                    fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);
                                    fileNameWithLength = fileNameWithLength.Replace("Head#", "").Trim();
                                    strSRecMsg = fileNameWithLength.Split('-').First(); //檔案名                                    
                                    fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());//檔案長度
                                }

                            }
                            catch (Exception ex)
                            {
                                IsHead = true;
                                fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);
                                strSRecMsg = fileNameWithLength.Split('-').First(); //檔案名
                                fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());//檔案長度
                            }

                      

                        }
    ///檔案傳輸儲存在IIS站點下
                        if (buffer[0] == 1)//1為檔案
                        {
                            bool IsOk = false;
                            string savePath = "";
                            if (IsHead)
                            {
                                savePath = [email protected]"C:\Files\UserHead\{strSRecMsg}";
                                IsOk = true;
                                //
                            }
                            else
                            {
                                //string fileNameSuffix = strSRecMsg.Substring(strSRecMsg.LastIndexOf('.')); //檔案字尾
                                //SaveFileDialog sfDialog = new SaveFileDialog()
                                //{
                                //    Filter = "(*" + fileNameSuffix + ")|*" + fileNameSuffix + "", //檔案類型
                                //    FileName = strSRecMsg
                                //};
                                //IsOk = sfDialog.ShowDialog(this) == DialogResult.OK;

                                savePath = [email protected]"C:\檔案\SocketUserInfo\{strSRecMsg}";
                                IsOk = true;
                               // savePath = sfDialog.FileName; //擷取檔案的全路徑
                            }
                           

                            //如果點選了對話框中的儲存檔案按鈕 
                            if (IsOk)
                            {                             
                                                                     //儲存檔案
                                int received = 0;
                                long receivedTotalFilelength = 0;
                                bool firstWrite = true;
                                using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                                {
                                    while (receivedTotalFilelength < fileLength) //之後收到的檔案位元組數組
                                    {
                                        if (firstWrite)
                                        {
                                            fs.Write(buffer, 1, firstReceived - 1); //第一次收到的檔案位元組數組 需要移除辨別符1 後寫入檔案
                                            fs.Flush();

                                            receivedTotalFilelength += firstReceived - 1;

                                            firstWrite = false;
                                            continue;
                                        }
                                        received = socketServer.Receive(buffer); //之後每次收到的檔案位元組數組 可以直接寫入檔案
                                        fs.Write(buffer, 0, received);
                                        fs.Flush();

                                        receivedTotalFilelength += received;
                                    }
                                    fs.Close();
                                    IsHead = false;
                                }

                                string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1); //檔案名 不帶路徑
                                string fPath = savePath.Substring(0, savePath.LastIndexOf("\\")); //檔案路徑 不帶檔案名
                                txtMsg.AppendText(GetCurrentTime() + "\r\n您成功接收了檔案" + fName + "\r\n儲存路徑為:" + fPath + "\r\n");
                                ClientSendMsg(ReceiveUserID, SendClientMsg, 2);
                            }
                        }
                        ///擷取線上使用者資訊
                        if (buffer[0] == 5)
                        {
                            string UserMsg = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);//真實有用的文本資訊要比接收到的少1(辨別符)
                            if (UserMsg == "001001001")
                            {
                                ServerSendClientOnLine();
                            }
                        }
                        if (buffer[0] == 4)
                        {
                            string UserMsg = Encoding.UTF8.GetString(buffer, 1, firstReceived - 1);//真實有用的文本資訊要比接收到的少1(辨別符)
                            var strMymsg = UserMsg.Split('#');
                            if (strMymsg[0] == "002002002")
                            {
                                MessageAmanager amanager = JsonConvert.DeserializeObject<MessageAmanager>(strMymsg[1]);
                                //MessageAmanager
                                //擷取通路用戶端的IP
                                clientIP = (socketServer.RemoteEndPoint as IPEndPoint).Address;
                                //擷取通路用戶端的Port
                                clientPort = (socketServer.RemoteEndPoint as IPEndPoint).Port;
                                //建立通路用戶端的唯一辨別 由IP和端口号組成 
                                clientName = "IP: " + clientIP + " Port: " + clientPort;
                                lstClients.Items.Remove(clientName);
                                lstClients.Items.Add(amanager.Message); //在用戶端清單添加該通路用戶端的唯一辨別
                                                                        //var dicSocketS= dicSocket.Where(x => x.Key == clientName).FirstOrDefault();
                                /// dicSocket.Add(clientName, socConnection); //将用戶端名字和套接字添加到添加到資料字典中
                                dicSocket = dicSocket.ToDictionary(k => k.Key == clientName ? amanager.Message : k.Key, k => k.Value);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    //dicSocket.Remove(dicSocket.Where(x => x.Value == socketServer).FirstOrDefault().Key);
                    txtMsg.AppendText("系統異常消息:" + ex.Message);
                    break;
                }
            }
        }



        //将資訊發送到到用戶端
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            ServerSendMsg(txtSendMsg.Text);
        }

        //快捷鍵 Enter 發送資訊
        private void txtSendMsg_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                ServerSendMsg(txtSendMsg.Text);
            }
        }

        /// <summary>
        /// 擷取目前系統時間
        /// </summary>
        public DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }

        //關閉服務端
        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        //取消用戶端清單選中狀态
        private void btnClearSelectedState_Click(object sender, EventArgs e)
        {
            lstClients.SelectedItem = null;
        }

        /// <summary>
        /// 發送資訊到用戶端的方法
        /// </summary>
        /// <param name="sendMsg">發送的字元串資訊</param>
        private void ServerSendClientOnLine()
        {
            //  ClearSockectClient();
            string Msg = "";
            foreach (var item in dicSocket)
            {
                if (string.IsNullOrEmpty(Msg))
                {
                    Msg += item.Key;
                }
                else
                {
                    Msg += "#" + item.Key;
                }
            }
            Msg = "0000100020003*" + Msg;

            //将輸入的字元串轉換成 機器可以識别的位元組數組
            byte[] arrSendMsg = Encoding.UTF8.GetBytes(Msg);

            //周遊所有的用戶端
            for (int i = 0; i < lstClients.Items.Count; i++)
            {
                try
                {
                    ClientSendMsg(lstClients.Items[i].ToString(), Msg, 0);
                    //dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg);
                }
                catch (Exception ex)
                {

                }

            }
            //txtMsg.AppendText("您在 " + GetCurrentTime() + " 群發了資訊:\r\n" + sendMsg + " \r\n");

        }

        //public void ClearSockectClient()
        //{
        //    string[] keyArr = dicSocket.Keys.ToArray<string>();
        //    for (int i = dicSocket.Count-1; i >=1; i--)
        //    {
        //        try
        //        {

        //            dicSocket[keyArr[i]].Send(Encoding.UTF8.GetBytes("001003"));
        //        }
        //        catch (Exception ex)
        //        {
        //            dicSocket.Remove(keyArr[i]);
        //        }
        //    }




        //}
        /// <summary>
        /// 發送字元串資訊到指定用戶端的方法
        /// </summary>
        private void ClientSendMsg(string Key, string sendMsg, byte symbol)
        {
            byte[] arrClientMsg = Encoding.UTF8.GetBytes(sendMsg);
            //實際發送的位元組數組比實際輸入的長度多1 用于存取辨別符
            byte[] arrClientSendMsg = new byte[arrClientMsg.Length + 1];
            arrClientSendMsg[0] = symbol;  //在索引為0的位置上添加一個辨別符
            Buffer.BlockCopy(arrClientMsg, 0, arrClientSendMsg, 1, arrClientMsg.Length);
            dicSocket[Key].Send(arrClientSendMsg);
         
            // txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");
        }
        ///計時器 定時清理無效連接配接
        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (var item in dicSocket.ToArray())
            {
                try
                {
                    item.Value.Send(Encoding.UTF8.GetBytes("001003"));
                }
                catch (Exception ex)
                {
                    lstClients.Items.Remove(item.Key);
                    dicSocket.Remove(item.Key);
                }


                //if (item.Value.Connected.)
                //{

                //}
            }
            if (dicSocket.Count == 0)
            {
                lstClients.Items.Clear();
            }
        }
    }

    /// <summary>
    ///消息管理
    /// </summary>
    public class MessageAmanager
    {
        /// <summary>
        /// 發送者ID
        /// </summary>
        public string SendUserID { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 接收者ID
        /// </summary>
        public string ReceiveUserID { get; set; }

    }
   ///消息管理
    public class MessageBox
    {
        /// <summary>
        /// 接收人
        /// </summary>
        public string RID { get; set; }

        public string Message { get; set; }

        public string Name { get; set; }
        /// <summary>
        /// 發送人
        /// </summary>
        public string SendID { get; set; }
    }

    /// <summary>
    /// 檔案發送管理
    /// </summary>
    public class ScokeSendFile
    {
        /// <summary>
        /// 檔案名稱
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// 解析檔案名稱
        /// </summary>
        public string FileNames { get; set; }
        /// <summary>
        /// 檔案資料
        /// </summary>
        public string FilePath { get; set; }

        /// <summary>
        /// 發送者ID
        /// </summary>
        public string SendUserID { get; set; }
        /// <summary>
        /// 接收者ID
        /// </summary>
        public string ReceiveUserID { get; set; }

        /// <summary>
        /// 0 圖檔 2 檔案
        /// </summary>
        public int Type { get; set; } = 0;
    }
}

           

下面是用戶端發送檔案實作: 注意發送檔案需要事先動态請求檔案讀寫權限 否則打開檔案将會報錯

public async Task<string> OnBrowse()
        {
            try
            {
                var pickFile = await CrossFilePicker.Current.PickFile();
                if (pickFile is null)
                {
                    return "";
                    // 使用者拒絕選擇檔案
                }
                else
                {
                    ScokeSendFile scokeFile = new ScokeSendFile();
                    scokeFile.FileName = pickFile.FileName;
                    scokeFile.FilePath = pickFile.FilePath;
                    scokeFile.ReceiveUserID = Id;
                    scokeFile.SendUserID = DeviceHelp.MyUserID;
                    scokeFile.Type = 2;
                    AddMyFile(scokeFile);
                    DeviceHelp.xamarinSockectClient.SenFile(scokeFile);

                    return pickFile.FilePath;
                    // FileText.Text = [email protected]"選取檔案路徑 :{pickFile.FilePath}";
                }


            }
            catch (Exception e)
            {
                return e.Message;
                //await DisplayAlert("Alert", "Something went wrong", "OK");
                //if (SettingsPage.loggingEnabled)
                //{
                //    LogUtilPage.Log(e.Message);
                //}
            }



        }




       ///Socke内檔案發送處理
            if (string.IsNullOrEmpty(scokeSendFile.FilePath))
            {              
                return;
            }
            fileName = scokeSendFile.FileName;
            //發送檔案之前 将檔案名字和長度發送過去
            long fileLength = new FileInfo(scokeSendFile.FilePath).Length;
            string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
            scokeSendFile.FileNames = totalMsg;
            string path = JsonConvert.SerializeObject(scokeSendFile);

            ClientSendMsg(path, 2);


            //發送檔案
            byte[] buffer = new byte[SendBufferSize];

            using (FileStream fs = new FileStream(scokeSendFile.FilePath, FileMode.Open, FileAccess.Read))
            {
                int readLength = 0;
                bool firstRead = true;
                long sentFileLength = 0;
                while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    //在第一次發送的位元組流上加個字首1
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        firstBuffer[0] = 1; //告訴機器該發送的位元組數組為檔案
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

                        socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);

                        firstRead = false;
                        continue;
                    }
                    //之後發送的均為直接讀取的位元組流
                    socketClient.Send(buffer, 0, readLength, SocketFlags.None);
                }
                fs.Close();
            }

           

下面是android端接受檔案處理

/// <summary>
       /// 好友發來的檔案
       /// </summary>
       /// <param name="scokeSendFile"></param>
       public void AddFriendFile(ScokeSendFile scokeSendFile)
       {
           Device.BeginInvokeOnMainThread(() =>
           {

               light monkey = new light();
               monkey.Text = scokeSendFile.FileName;
               monkey.TextIsVisibles = false;
               monkey.ImageIsVisibles = true;
               var fileKZName = Path.GetExtension(scokeSendFile.FilePath).ToLower();
               if (scokeSendFile.Type == 2 && !_fileNameKZ.Contains(fileKZName.ToLower()))
               {
                   monkey.ImageUrl = "wj.png";
                   monkey.FilePath = "wj.png";
               }
               else
               {
                    monkey.ImageUrl = scokeSendFile.FilePath;
                   //monkey.ImageUrl = "wj.png";
                   monkey.FilePath = scokeSendFile.FilePath;
               }
               //  monkey.ImageUrl = ""; //"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"// "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
               monkey.FriendImageIsVisibles = true;

               monkey.FriendImageUrl = "https://profile.csdnimg.cn/8/5/A/1_psu521";
               monkey.MyImageIsVisibles = false;
               //   monkey.Click += new EventHandler(Click);
               monkey.TextHorizontalOptions = LayoutOptions.Start;
               //monkey.Grd_Heigt = 200;
               //monkey.Grd_Heigt = monkey.Text.Length >= 20 ? (monkey.Text.Length / 20) * 24 : 40;  //GridLength.Auto;
               //monkey.TextWidth = monkey.Text.Length > 17 ? App.ScreenWidth - 110 : (App.ScreenWidth - 110) * (monkey.Text.Length * 0.018);
               monkey.Grd_Heigt = (monkey.Text.Length >= 10 ? (monkey.Text.Length / 7) * 24 : 40) + 30;  //GridLength.Auto;
               monkey.TextWidth = monkey.Text.Length > (App.ScreenWidth - 110) / 24 ? App.ScreenWidth - 110 : (App.ScreenWidth - 50) * (monkey.Text.Length * 0.08);
               monkey.MsgTime = DateTime.Now.ToString();
               // HomeViewModel.AddFiyee(monkey);
               lights.Add(monkey);
               X_listView_ScrollTo();

               //SampleMessage sample = new SampleMessage { Text = box.Message, Id = box.SendID };
               //sample.User = new SampleUser() { Id = box.SendID, Avatar = box.Name, Name = box.Name };

               //messagesListAdapter.AddToStart(sample, true);
           });
       }
           

下面是檢視檔案處理 通過httpClient 下載下傳檔案

private async void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {
            try
            {
                //ImageViewPage
                if (sender is MyImage)
                {
                    MyImage myImage = sender as MyImage;

                    var data = lights.Where(x => x.ID == myImage.Text).FirstOrDefault();
                    var fileKZName = Path.GetExtension(data.FilePath).ToLower();
                    ///如果是圖檔類型 則打開一個image頁面 顯示 否則就跳轉到浏覽器打開
                    if (myImage.imageType == ImageType.body && _fileNameKZ.Contains(fileKZName.ToLower()))
                    {
                        if (data.FriendImageIsVisibles)
                        {
                            var httpData =  HttlClientDow(data.FilePath);           
                             
                            Navigation.PushAsync(new ImageViewPage(ImageSource.FromStream(() => httpData)), true);
                        }
                        else
                        {
                            Navigation.PushAsync(new ImageViewPage(myImage.Source), true);
                        }
                    }
                    else
                    {
                    ///浏覽器打開檔案
                        await Browser.OpenAsync(data.FilePath, new BrowserLaunchOptions
                        {
                            LaunchMode = BrowserLaunchMode.SystemPreferred,
                            TitleMode = BrowserTitleMode.Show,
                            PreferredToolbarColor = Color.AliceBlue,
                            PreferredControlColor = Color.Violet
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                DevHelp.DeviceHelp.Toast.ShortAlert(ex.Message);
            }
        }
 
           

下面是效果圖:程式内打開

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:
xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:

跳轉浏覽器打開

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊:

自此完結 謝謝大家

需要源碼請聯系部落客微信:

xamarin.android 即時通訊 檔案傳輸1.服務端的作用:2.用戶端與用戶端通訊: