您好,登錄后才能下訂單哦!
今天給大家介紹一下如何實現(xiàn)ESFramework4.0文件傳送。文章的內(nèi)容小編覺得不錯,現(xiàn)在給大家分享一下,覺得有需要的朋友可以了解一下,希望對大家有所幫助,下面跟著小編的思路一起來閱讀吧。
ESFramework,是一套可高度復(fù)用的、靈活的、單純而又強大的.NET通信框架,全部采用C#編寫。ESFramework內(nèi)置了對Tcp和Udp的支持,并且支持文本協(xié)議和流協(xié)議,提供了多種網(wǎng)絡(luò)引擎供服務(wù)端和客戶端開發(fā)人員輕松使用。采用ESFramework框架,使得您不需要了解Socket、不用再關(guān)心底層與通信相關(guān)的一切瑣碎的事情,就可以在一個更高的層次上更快地開發(fā)屬于您的高效穩(wěn)定的網(wǎng)絡(luò)通信應(yīng)用。像IM系統(tǒng)、視頻會議系統(tǒng)、數(shù)據(jù)采集系統(tǒng)等,凡是需要分布式通信的系統(tǒng)都可以使用ESFramework框架。
一.ESPlus的文件傳送流程
ESPlus定義了文件傳送的標準流程,可以用下圖表示:
(1)由發(fā)送方發(fā)起傳送文件的請求。
(2)接收方回復(fù)同意或者拒絕接收文件。如果拒收,則流程結(jié)束;否則進入下一步。
(3)發(fā)送方發(fā)送文件數(shù)據(jù),接收方接收文件數(shù)據(jù)。
(4)如果文件傳送過程中,接收方或發(fā)送方掉線或者取消文件傳送,則文件傳送被中斷,流程結(jié)束。如果文件傳送過程一直正常,則到***完成文件的傳送。
有幾點需要說明一下:
(1)發(fā)送方可以是客戶端,也可以是服務(wù)器;接收方也是如此。但無論發(fā)送方和接收方的類別如何,它們都遵守這一文件傳送流程;就像ESFramework所有的通信引擎都公用同一套消息處理骨架流程一樣。
(2)當接收方同意接收后,框架會自動搜索是否存在匹配的續(xù)傳項目,若存在,則會啟動斷點續(xù)傳。當然,我們可以通過文件接收管理器的屬性來控制斷點續(xù)傳功能是否開啟。關(guān)于斷點續(xù)傳的更多內(nèi)容,可以參考ESFramework 4.0 文件斷點續(xù)傳原理與實現(xiàn)。
(3)進行文件傳送的線程是由框架自動控制的,只要發(fā)送方收到了接收方同意接收的回復(fù),框架就會自動在后臺線程中發(fā)送文件數(shù)據(jù)包;同樣,此時接收方也會自動處理接收到的文件數(shù)據(jù)包。
(4)發(fā)送方或接收方都可隨時取消正在傳送的文件。
(5)當文件傳送被中斷或完成時,發(fā)送方和接收方都會有相應(yīng)的事件通知。
二.ESPlus用于支持文件傳送的基礎(chǔ)設(shè)施
1.TransmittingFileInfo
無論是發(fā)送方還是接收方,針對每個文件傳送任務(wù),都需要有個對象來表示它,TransmittingFileInfo便是一個文件傳送項目的封裝,里面包含了類似發(fā)送者ID、接收者ID、文件名稱等相關(guān)信息。
TransmittingFileInfo的大部分屬性對于發(fā)送方和接收方都是有效的,而有幾個屬性只對發(fā)送方有效(比如SendingFileParas),有幾個屬性只對接收方有效(如LocalSaveFilePath),這些在幫助文檔中都有詳細的說明。而且,有些屬性(如OriginFileLastUpdateTime)的存在是用于支持斷點續(xù)傳功能的。
2.FileTransDisrupttedType
ESPlus使用FileTransDisrupttedType枚舉定義了所有可能導(dǎo)致文件傳送中斷的原因:
public enum FileTransDisrupttedType { /// <summary> /// 自己主動取消 /// </summary> ActiveCancel, /// <summary> /// 對方取消 /// </summary> DestCancel, /// <summary> /// 對方掉線 /// </summary> DestOffline, /// <summary> /// 網(wǎng)絡(luò)中斷、自己掉線 /// </summary> SelfOffline, /// <summary> /// 對方拒絕接收文件 /// </summary> DestReject, /// <summary> /// 其它原因,如文件讀取失敗等 /// </summary> OtherCause }
3.IFileTransferingEvents 接口
ESPlus定義了IFileTransferingEvents接口,用于暴露所有與文件傳送相關(guān)的狀態(tài)和事件:
public interface IFileTransferingEvents { /// <summary> /// 當某個文件開始傳送時,觸發(fā)該事件。 /// </summary> event CbGeneric<TransmittingFileInfo> FileTransStarted; /// <summary> /// 當某個文件續(xù)傳開始時,觸發(fā)該事件。(將不再觸發(fā)FileTransStarted事件) /// </summary> event CbGeneric<TransmittingFileInfo> FileResumedTransStarted; /// <summary> /// 文件傳送的進度。參數(shù)為fileID(文件編號) ,total(文件大小) ,transfered(已傳送字節(jié)數(shù)) /// </summary> event CbFileSendedProgress FileTransProgress; /// <summary> /// 文件傳送中斷時,觸發(fā)該事件。 /// </summary> event CbGeneric<TransmittingFileInfo, FileTransDisrupttedType> FileTransDisruptted; /// <summary> /// 文件傳送完成時,觸發(fā)該事件。 /// </summary> event CbGeneric<TransmittingFileInfo> FileTransCompleted; }
通過預(yù)定這些事件,我們可以知道每個傳送的文件什么時候開始(或斷點續(xù)傳)、什么時候完成、傳遞的實時進度、傳送中斷的原因等等。要注意的是,這些事件都是在后臺線程中觸發(fā)的,如果在事件處理函數(shù)中需要更新UI,則需要將調(diào)用轉(zhuǎn)發(fā)到UI線程。
4.SendingFileParas
該對象僅僅包含兩個屬性:SendingSpanInMSecs和FilePackageSize。發(fā)送方可以通過SendingFileParas對象來指定發(fā)送文件數(shù)據(jù)包時的頻率與每個數(shù)據(jù)包的大小。一般來說,為了達到最快的傳送速度,SendingSpanInMSecs可以設(shè)為0。而FilePackageSize的大小則要根據(jù)發(fā)送方與接收方的網(wǎng)絡(luò)環(huán)境的好壞進行決定,在Internet上,一般可以設(shè)為2048或4096左右;而在局網(wǎng)內(nèi),可以設(shè)為204800甚至更大(在局網(wǎng)的傳送速度可以達到30M/s以上)。
5.IFileController
通過ESPlus.Application.FileTransfering.IFileController接口,我們可以提交發(fā)送文件的請求,并且可以主動取消正在接收或發(fā)送的文件。IFileController即可用于客戶端也可用戶服務(wù)端。
public interface IFileController { /// <summary> /// 該事件接口暴露了所有正在發(fā)送文件的實時狀態(tài)。 /// </summary> IFileTransferingEvents FileSendingEvents { get; } /// <summary> /// 該事件接口暴露了所有正在接收的文件的實時狀態(tài)。 /// </summary> IFileTransferingEvents FileReceivingEvents { get; } /// <summary> /// 準備發(fā)送文件。如果對方同意接收,則后臺會自動發(fā)送文件;如果對方拒絕接收,則會取消發(fā)送。 /// 如果要發(fā)送的文件不存在或被占用,則將拋出對應(yīng)的異常。 /// </summary> /// <param name="accepterID">接收文件的用戶ID</param> /// <param name="filePath">被發(fā)送文件的路徑</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務(wù)中,該參數(shù)可以是保存文件的路徑</param> /// <param name="fileID">返回即將發(fā)送文件的唯一編號</param> void BeginSendFile(string accepterID, string filePath, string comment, out string fileID); /// <summary> /// 準備發(fā)送文件。如果對方同意接收,則后臺會自動發(fā)送文件;如果對方拒絕接收,則會取消發(fā)送。 /// 如果要發(fā)送的文件不存在或被占用,則將拋出對應(yīng)的異常。 /// </summary> /// <param name="accepterID">接收文件的用戶ID</param> /// <param name="filePath">被發(fā)送文件的路徑</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務(wù)中,該參數(shù)可以是保存文件的路徑</param> /// <param name="paras">發(fā)送參數(shù)設(shè)定。傳入null,表示采用IFileSenderManager的默認設(shè)置。</param> /// <param name="fileID">返回即將發(fā)送文件的唯一編號</param> void BeginSendFile(string accepterID, string filePath, string comment,SendingFileParas paras, out string fileID); /// <summary> /// 主動取消正在發(fā)送或接收的文件,并通知對方。 /// </summary> void CancelFileTransfering(string fileID); /// <summary> /// 取消與某個用戶相關(guān)的正在傳送項目。 /// </summary> /// <param name="destUserID">目標用戶ID。</param> void CancelFileTransferingAbout(string destUserID); /// <summary> /// 獲取正在發(fā)送或接收中的文件的相關(guān)信息。 /// </summary> TransmittingFileInfo GetFileInfo(string fileID); }
(1)BeginSendFile用于向接收方提交發(fā)送文件的請求,如果對方同意,則后臺會自動開始傳遞文件。該方法有個out參數(shù)fileID,用于傳出標記該文件傳送項目的唯一編號,比如,你打算將同一個文件發(fā)送給兩個好友,將會調(diào)用兩次BeginSendFile方法,而兩次得到的fileID是不一樣的。也就是說,fileID是用于標記文件傳送項目的,而不是標記文件的。
該方法有兩個重載,區(qū)別在于第二個BeginSendFile方法多了一個SendingFileParas參數(shù),用于主動控制文件數(shù)據(jù)包的大小和發(fā)送頻率。
在客戶端使用時,BeginSendFile方法不僅可以向其他在線用戶提交發(fā)送文件的請求,也可以直接向服務(wù)器提交發(fā)送文件的請求 -- 即此時文件的接收者為服務(wù)端。我們只需要將accepterID參數(shù)傳入NetServer.SystemUserID,以指明由服務(wù)端而不是其他用戶來接收即將發(fā)送的文件。
(2)GetFileInfo方法可以獲取任何一個正在發(fā)送或正在接收的項目信息。
(3)CancelFileTransfering方法用于取消正在發(fā)送或接收的某個文件傳送項目,調(diào)用該方法時,框架會自動通知文件傳送的另一端用戶,并觸發(fā)FileReceivingEvents或FileSendingEvents中的FileTransDisruptted事件,而另一端也會自動觸發(fā)FileTransDisruptted事件。
(4)CancelFileTransferingAbout方法用于取消與某個指定用戶相關(guān)的正在傳送項目。比如,我們正在與aa01用戶聊天,并且與aa01有多個文件正在傳送,此時,如果要關(guān)閉與aa01的聊天窗口,那么關(guān)閉之前,通常會先調(diào)用CancelFileTransferingAbout方法來取消與aa01相關(guān)的所有文件傳送。所以你經(jīng)常會看到類似的提示:“您與aa01有文件正在傳送中,關(guān)閉當前窗口將導(dǎo)致正在傳送的文件中斷,您確定要關(guān)閉嗎?”。如果用戶確認關(guān)閉,此時就正是我們要調(diào)用CancelFileTransferingAbout方法的時候了。
(5)FileSendingEvents屬性用于暴露自己作為發(fā)送者的所有正在進行的文件傳送項目的實時狀態(tài);FileReceivingEvents屬性用于暴露自己作為接收者的所有正在進行的文件傳送項目的實時狀態(tài)。
6.IFileHandler
IFileHandler接口將被框架回調(diào)以實現(xiàn)文件傳送機制。同IFileController一樣,其既可用于客戶端也可用戶服務(wù)端。
我們需要實現(xiàn)ESPlus.Application.FileTransfering.IFileHandler接口來獲取與文件傳送請求相關(guān)通知:
public interface IFileBusinessHandler : IBusinessHandler { /// <summary> /// 是否同意接收文件? /// </summary> /// <param name="senderID">發(fā)送者的ID。如果為NetServer.SystemUserID,則表示是服務(wù)端發(fā)送的。</param> /// <param name="fileName">文件名稱。</param> /// <param name="fileLength">文件大小。</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務(wù)中,該參數(shù)可以是保存文件的路徑</param> /// <param name="fileID">文件ID。</param> /// <param name="resumedFileItem">如果能續(xù)傳,則不為null。</param> /// <returns>返回值為保存文件的路徑,如果為null,表示拒絕接收/拒絕續(xù)傳文件。如果參數(shù)resumedFileItem不為null,而且返回路徑等于resumedFileItem.LocalFileSavePath,則表示續(xù)傳;否則表示另存。</returns> string ReadyToAcceptFile(string senderID, string fileName, long fileLength, string comment, string fileID, ResumedFileItem resumedFileItem); /// <summary> /// 接收者對自己發(fā)送文件請求的回復(fù) -- 同意/拒絕接收。 /// </summary> /// <param name="info">文件傳送項目的相關(guān)信息</param> /// <param name="agreed">對方是否同意</param> void OnResponseOfReceiver(TransmittingFileInfo info ,bool agreed); }
(1)ReadyToAcceptFile方法是當前用戶作為接收方時被框架回調(diào)的;而OnResponseOfReceiver方法是當前用戶作為發(fā)送方時,被框架回調(diào)的。
(2)IFileHandler接口的兩個方法都將在后臺線程中被框架調(diào)用,如果實現(xiàn)該方法時需要刷新應(yīng)用程序的UI,則注意一定要轉(zhuǎn)發(fā)到UI線程。
(3)當發(fā)送方提交了發(fā)送文件的請求后,框架會在接收方回調(diào)ReadyToAcceptFileAsyn方法以詢問是否同意接收,如果同意,ReadyToAcceptFileAsyn應(yīng)返回有效的存儲接收文件的路徑,否則,返回null。
(4)當接收方同意或拒絕接收文件,框架會在發(fā)送方回調(diào)OnResponseOfReceiver方法以通知發(fā)送者。通常,應(yīng)用程序在實現(xiàn)OnResponseOfReceiver方法時,最多只需要告知文件發(fā)送者,而不需要再做任何其它的額外處理。因為框架已經(jīng)幫你打理好了一切。
當接收方同意接收文件后,與該文件傳送項目相關(guān)的事件會通過IFileOutter暴露的IFileTransferingEvents接口相繼觸發(fā)。
三.客戶端
同ESPlus的Basic應(yīng)用或CustomizeInfo應(yīng)用一樣,在客戶端支持文件傳送功能也需要使用到相應(yīng)的“Outter”組件和實現(xiàn)相應(yīng)的“BusinessHandler”接口。
1.IFileOutter
ESPlus.Application.FileTransfering.Passive.IFileOutter接口從IFileController繼承,并增加了一個屬性和一個方法: public interface IFileOutter : IOutter ,IFileController { /// <summary> /// 發(fā)送文件數(shù)據(jù)包時所采用的消息優(yōu)先級。 /// </summary> DataPriority DataPriority4SendingFile { get; set; } /// <summary> /// 初始化文件傳送查看器控件。 /// </summary> /// <param name="viewer">文件傳送查看器控件對象</param> /// <param name="destUserID">目標用戶的ID。返回的查看器將顯示與該用戶相關(guān)的所有文件傳送狀態(tài)。如果傳入null,則顯示與任何用戶的文件傳送的實時狀態(tài)。</param> void InitializeFileTransferingViewer(FileTransferingViewer viewer, string destUserID); }
(1)我們可以通過設(shè)置DataPriority4SendingFile屬性以控制發(fā)送文件數(shù)據(jù)包的優(yōu)先級,在一般系統(tǒng)中,可以將其設(shè)置為Common或Low,但絕不能設(shè)置為CanBeDiscarded,否則將可能導(dǎo)致接收方接收到的文件不完整。
(2)ESPlus提供了默認的傳送項目的狀態(tài)查看器控件FileTransferingViewer,如果沒有特殊需求,大家在項目中可以直接使用它來顯示文件傳送的實時狀態(tài),它的界面截圖如下所示:
你只需要把這個控件拖拽到你的UI上,然后將其傳入IFileOutter的InitializeFileTransferingViewer方法進行初始化后,它就會正常工作了。
InitializeFileTransferingViewer方法的第二個參數(shù)destUserID表示當前的FileTransferingViewer控件要顯示與哪個好友相關(guān)的所有文件傳送項目的狀態(tài)。以QQ作類比,你同時在與多個好友傳送文件,那么就會有多個聊天窗口,每個聊天窗口都會有一個FileTransferingViewer實例,而這個FileTransferingViewer實例僅僅顯示與當前聊天窗口對應(yīng)的好友的傳送項目。這樣依賴,你與aa01用戶傳送文件的進度查看器就不會在你與aa02的聊天窗口上顯示出來。
如果你的FileTransferingViewer查看器需要捕捉所有正在傳送的項目的實時狀態(tài),那么,調(diào)用InitializeFileTransferingViewer方法時,destUserID參數(shù)可以傳入null。
另外,F(xiàn)ileTransferingViewer實現(xiàn)了IFileTransferingViewer接口:
public interface IFileTransferingViewer { /// <summary> /// 當某個文件開始續(xù)傳時,觸發(fā)該事件。參數(shù)為FileName - isSend /// </summary> event CbGeneric<string, bool> FileResumedTransStarted; /// <summary> /// 當某個文件傳送完畢時,觸發(fā)該事件。參數(shù)為FileName - isSend /// </summary> event CbGeneric<string, bool> FileTransCompleted; /// <summary> /// 當某個文件傳送中斷時,觸發(fā)該事件。參數(shù)為FileName - isSend - FileTransDisrupttedType /// </summary> event CbGeneric<string, bool, FileTransDisrupttedType> FileTransDisruptted; /// <summary> /// 當某個文件傳送開始時,觸發(fā)該事件。參數(shù)為FileName - isSend /// </summary> event CbGeneric<string, bool> FileTransStarted; /// <summary> /// 當所有文件都傳送完成時,觸發(fā)該事件。 /// </summary> event CbSimple AllTaskFinished; /// <summary> /// 當點擊取消按鈕終止某個文件傳送時,觸發(fā)該事件。 /// </summary> event CbCancelFile CancelFileButtonClicked; /// <summary> /// 當前是否有文件正在傳送中。 /// </summary> bool IsFileTransfering(); }
你也可以通過該接口來關(guān)注FileTransferingViewer查看器捕捉到的(正如前所述,不一定是全部)文件傳送項目的狀態(tài),而且,該接口的事件都是在UI線程中觸發(fā)的,你可以直接在其處理函數(shù)中操控UI顯示。
2.IFileBusinessHandler
客戶端的ESPlus.Application.FileTransfering.Passive.IFileBusinessHandler直接從IFileHandler繼承,而且沒有增加額外的內(nèi)容:
public interface IFileBusinessHandler : IBusinessHandler, IFileHandler { }
四.服務(wù)端
服務(wù)端也可以接收客戶端發(fā)送的文件(即上傳),甚至可以發(fā)送文件給客戶端(即下載),它遵循同樣的文件傳送流程。
1.IFileTransferingController
如果需要服務(wù)端也參與到文件的發(fā)送與接收中來,則同客戶端一樣,服務(wù)端的ESPlus.Application.FileTransfering.Server.IFileTransferingController接口也從IFileController繼承,以提交文件發(fā)送請求、或取消正在發(fā)送中的文件等,這里就不重復(fù)解釋了。
2.IFileBusinessHandler
服務(wù)端需要實現(xiàn)ESPlus.Application.FileTransfering.Server.IFileBusinessHandler接口,也是直接從IFileHandler繼承,而且沒有增加額外的內(nèi)容。
五.Rapid引擎對文件傳送的支持
新版本的Rapid引擎(可以從ESFramework 4.0 概述文末下載 ),增加了對文件傳送的支持,使用Rapid引擎的朋友可以很方便的利用框架提供的文件傳送功能。
1.客戶端
IRapidPassiveEngine的Initialize方法增加了一個重載:
void Initialize(string userID, string serverIP, int serverPort, IBasicBusinessHandler basicHandler, ICustomizeInfoBusinessHandler customizeHandler ,IFileBusinessHandler fileHandler);
該重載增加了一個IFileBusinessHandler參數(shù),用于支持文件傳送機制。
另外,IRapidPassiveEngine增加了一個IFileOutter只讀屬性,通過暴露的該屬性,我們就可以提交發(fā)送文件的請求或監(jiān)控文件傳送的狀態(tài)了。當然,如果在Initialize方法中沒有傳入有效的IFileBusinessHandler引用,則FileOutter屬性將返回null。
2.服務(wù)端
同客戶端一樣,服務(wù)端IRapidServerEngine的Initialize方法也增加了一個重載:
void Initialize(int port, ICustomizeInfoBusinessHandler customizeInfoBusinessHandler,IFileBusinessHandler fileBusinessHandler, IFriendsManager friendsManager, IGroupManager groupManager);
IRapidServerEngine提供了IFileTransferingController只讀屬性,用于提交發(fā)送文件的請求或監(jiān)控文件傳送的狀態(tài)。同樣的,如果在Initialize方法中沒有傳入有效的IFileBusinessHandler引用,則FileTransferingController屬性將返回null。
Rapid引擎已經(jīng)為我們組裝好了與文件傳送相關(guān)的所有組件,我們直接使用即可。如果后面有時間,我們會更深入地剖析ESPlus的文件傳送機制背后的原理,以及如何一步步地搭建起文件傳送的功能。
ESPlus使得在基于ESFramework的通信系統(tǒng)中增加文件傳送的功能變得如此簡單,甚至,基于ESPlus提供的文件傳送功能,我們可以很快地實現(xiàn)文件服務(wù)器,以支持文件上傳和下載。
以上就是如何實現(xiàn)ESFramework4.0文件傳送的全部內(nèi)容了,更多與如何實現(xiàn)ESFramework4.0文件傳送相關(guān)的內(nèi)容可以搜索億速云之前的文章或者瀏覽下面的文章進行學習哈!相信小編會給大家增添更多知識,希望大家能夠支持一下億速云!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。