天天看點

如何實作離線檔案?1.用戶端發送離線檔案2.服務端接收離線檔案      3.服務端發送離線檔案給最終接收者

      近段時間,有幾個朋友問我如何實作類似QQ離線檔案的功能。不想一一作答,就寫一篇博文來比較完整的解釋這個問題。

      下面我們就使用者在使用離線檔案時,按各個動作發生的先後順序,介紹程式方面與之對應的設計與實作。

      當使用者選擇好一個檔案,并點選“發送離線檔案”按鈕時,其目的是要将這個檔案傳送給服務端,這可以直接使用IFileOutter的BeginSendFile方法:

      如果将參數accepterID傳入null,表示檔案的接收者就是服務端。那麼我們要如何區分,這不是一個最終由服務端接收的檔案,而是要傳給另一個使用者的離線檔案了?這裡,我們可以巧用comment參數,比如,comment參數如果為null,就表示普通的上傳檔案;comment不為null,就表示一個離線檔案,并且其值就是檔案最終接收者的ID。(當然,如果在你的項目中,comment參數已經有了其它用途,我們可以進一步擴充它,加上一些标簽,使其能夠标志出離線檔案)。

      下面這個調用示例,就是将Test.txt檔案離線發送給aa01。

      用戶端調用BeginSendFile方法請求發送檔案後,服務端會觸發IFileController的FileRequestReceived事件。同理,我們判斷該事件的comment參數,當其不為null時,表示是個離線檔案。在答複用戶端同意接收檔案之前,我們需要先将離線檔案的相關資訊儲存起來,這裡我們使用OfflineFileItem類來封裝這些資訊。

        有了OfflineFileItem的定義之後,我們就可以處理IFileController的FileRequestReceived事件了。 

      上面的代碼做了三件事情:

(1)根據某種政策得到存放檔案的路徑。

(2)建立一個離線檔案資訊條目,儲存在記憶體中。

(3)回複用戶端,并準備接收檔案。

    需要重點說明的是第一點,對于一般的小型項目,在服務端我們可以将所有的離線檔案存放在目前伺服器的某個目錄下;但是對于大型項目,一般需要使用DFS(分布式檔案系統)來存儲這些臨時的離線檔案。

    用戶端收到伺服器的回複後,會正式開始傳送檔案,如果傳送過程中,因為某種原因導緻傳送中斷,則服務端會觸發IFileController.FileReceivingEvents的FileTransDisruptted事件。在該事件處理函數中,我們從記憶體中移除對應的離線檔案資訊條目: 

      如果檔案正常傳送完畢,則服務端會觸發IFileController.FileReceivingEvents的FileTransCompleted事件。此時,我們将對應的離線檔案資訊條目從記憶體轉移存儲到資料庫中,以防止伺服器重新開機時導緻資訊丢失: 

       我們設計IOfflineFilePersister接口,用于與資料庫中的OfflineFileItem表互動。 

       我們可以使用ADO.NET或者EntityFramework實作上述接口。

      當真正的接收者上線時,服務端要把相關的離線檔案發送給他。通過預定UserManager的SomeOneConnected事件,我們知道使用者上線的時刻。 

(1)從資料庫中查找所有接收者為登入使用者的離線檔案資訊條目。

(2)将離線檔案逐個發送給這個使用者

(3)從資料庫中删除相應的條目,從磁盤上删除對應的離線檔案。

      實際上,第(3)點我們可以延遲到檔案發送完成時,才執行删除操作。這樣,就可以在發送萬一意外中斷時,使得重新發送成為可能。

      用戶端接收到服務端的發送檔案請求時,會觸發IFileOutter的FileRequestReceived事件,此時也可以根據comment參數的内容,來判斷其是否為離線檔案。後續的步驟的實作就相當容易了,這裡就不再贅述了。

      本文簡潔地描述了實作離線檔案功能的主要思路和基本模型,在實際的項目開發時,可以根據具體的需求在這個模型的基礎上,進一步完善,包括很多細節和異常處理都需要加入進來。