ESFramework Demo -- 文件传送Demo(附源码)

      现在我们将在ESFramework Demo -- 入门Demo,简单的即时通讯系统 的基础上,使用ESPlus提供的第三个武器,为其增加文件传送的功能。在阅读本文之前,请务必先掌握ESFramework 开发手册(03) -- 文件(夹)传送 一文中介绍的文件传送的流程及相关的API的用法。

      本文的demo仅仅实现了客户端与客户端之间的文件传送,至于传送文件夹,以及服务器与客户端之间的文件传送则采用完全一样的模型,大家可以在本demo的基础上自行扩展。

      本Demo演示以下与文件传送相关的特性:

(1)发送方请求发送文件,接收方可以同意或拒绝接收文件。

(2)文件传送的过程中,收发的任何一方都可以通过事件了解文件传送的实时进度。

(3)文件传送的过程中,收发的任何一方都可以中断文件的传送。

(4)文件传送的过程中,收发的任何一方掉线,都将导致文件传送中断。

(5)只要文件传送中断,收发方都会得到相应的事件通知。

(6)自动启用文件断点续传。

(7)文件传送完成,收发方都会得到相应的事件通知。

一.服务端

      由于在demo中,服务端不参与文件传送,所以,服务端的代码不用做任何修改,直接使用上一个demo中的服务端即可。

      顺便提一下,如果想让服务端作为文件收发的一方,也很容易,只要遵循以下几点:

(1)使用IRapidServerEngine暴露的FileController属性,来控制文件的收发行为。

(2)预定IFileController的FileSendingEvents事件和FileReceivingEvents事件,来跟踪文件传送的实时状态。

(3)服务端的虚拟帐号为NetServer.SystemUserID,即"_0"。当一个文件的接收者的UserID为NetServer.SystemUserID,表示文件是由服务端接收的;当一个文件的发送者的UserID为NetServer.SystemUserID,表示这个文件是由服务端发送的。   

 二.客户端 

      相对于上一个demo,客户端改动的地方主要集中在MainForm和ChatForm上。客户端使用IRapidPassiveEngine暴露的FileOutter属性,来控制文件的收发行为。

发送与接收流程实现

      首先,ChatForm的最上方增加了一个“发送文件”的按钮,点击此按钮的时候,将选择文件,并请求发送。此时,客户端作为发送方的身份出现。

  //请求发送文件       
  private void toolStripButton1_Click(object sender, EventArgs e)
{
string filePath = ESBasic.Helpers.FileHelper.GetFileToOpen("打开");
if (filePath == null)
{
return;
}
string fileID;
SendingFileParas sendingFileParas = new SendingFileParas(20480, 0);//文件数据包大小,可以根据网络状况设定,局网内可以设为204800,传输速度可以达到30M/s以上;公网建议设定为2048或4096或8192
      this.fileOutter.BeginSendFile(this.friendID, filePath, null, sendingFileParas, out fileID);
}

      其次,客户端在MainForm的Initialize方法中通过预定IRapidPassiveEngine的FileOutter的FileRequestReceived事件,来获得接收到了文件传送请求的通知。此时,客户端是作为接收方的身份出现。

  //预定收到了来自发送方发送文件(夹)的请求的事件
  this.rapidPassiveEngine.FileOutter.FileRequestReceived += new CbFileRequestReceived(fileOutter_FileRequestReceived);

      注意,FileRequestReceived事件有个ResumedProjectItem类型的参数,用于表示当前传送项目是否能够续传。如果该参数不为null,则表示可以续传;如果该参数为null,则表示是一个全新的传送项目,不能续传。

      在该事件的处理函数中,最终会弹出MessageBox,询问用户是否同意接收,如果同意,则选择保存路径。根据用户的操作,我们需要将是否同意接收文件的答案通知给发送方。即ChatForm的OnFileRequest方法:

  //当接收到对方的文件传送请求时
  public void OnFileRequest(string fileID, string senderID, string fileName)
{
if (DialogResult.OK == MessageBox.Show(string.Format("{0}要求向你传输文件{1},你是否同意接收?", senderID, fileName), "文件传输", MessageBoxButtons.OKCancel))
{
string savePath = ESBasic.Helpers.FileHelper.GetPathToSave("保存", fileName, null);
if (!string.IsNullOrEmpty(savePath))
{
this.fileOutter.BeginReceiveFile(fileID, savePath);
}
else
{
this.RejectFile(fileID, fileName);
}
}
else
{
this.RejectFile(fileID, fileName);
}
}
  private void RejectFile(string fileID, string fileName)
  {
      TransferingProject fileInfo = this.fileOutter.GetTransferingProject(fileID);
      if (fileInfo != null)
      {
          this.textChatControl1.ShowRejectFile(fileName);
          this.fileOutter.RejectFile(fileID);
       }
  }

      发送方又是在MainForm的Initialize方法中通过预定IRapidPassiveEngine的FileOutter的FileResponseReceived事件,来得到对方的回复的:

  //预定接收方回复了同意/拒绝接收文件(夹)时的事件
  this.rapidPassiveEngine.FileOutter.FileResponseReceived += new CbGeneric<TransferingProject, bool>(fileOutter_FileResponseReceived);    

      如果对方同意接收,则ESPlus会在后台自动启动文件发送线程进行文件发送。

      客户端无论是作为发送方还是接收方,都在ChatForm中使用了FileTransferingViewer控件来显示各个文件传送项目的实时状态,并且通过预定其状态变化事件来接收通知,然后在聊天窗口中显示相应的信息。

 

      Demo运行起来后,传送文件的截图如下所示:

    

 

      当关闭聊天窗口ChatForm时,判断当前是否有文件正在传输。如果有,则提醒用户,如果用户仍然决定关闭,则在关闭窗体之前先要取消相关的正在传送的项目。

  private void ChatForm_FormClosing(object sender, FormClosingEventArgs e)
{
List<string> fileIDs = this.fileOutter.GetTransferingAbout(this.friendID);
if (fileIDs != null && fileIDs.Count > 0)
{
DialogResult result = MessageBox.Show("如果关闭窗口,就会中止文件传送。是否关闭窗口?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.None);
if (result == DialogResult.OK)
{
this.fileOutter.CancelTransferingAbout(this.friendID);
}
else
{
e.Cancel = true;
}
}

}

 断点续传

      当文件传送中断(比如因为掉线)后,发送方再次发送该文件,此时如果接收方同意接收,并且保存的路径与上次完全一致,那么框架底层将自动启用断点续传。 发送方和接收方以预定了FileTransferingViewer的FileResumedTransStarted事件,来得知断点续传启动的信息。

      更简单的,就像前面提到的,FileRequestReceived事件的ResumedProjectItem类型的参数,如果其值不为null,则表示可以续传。如果用户选择了续传,则就直接使用ResumedProjectItem的LocalSavePath属性的值作为文件存储路径,去调用IFileOutter的BeginReceiveFile方法就可以了。有兴趣的朋友,可以按照这种模式修改一下demo代码,就可以完全达到类似QQ的续传效果。

三.FileTransferingViewer控件

      FileTransferingViewer控件用于显示每个文件传送项目的实时状态。与QQ的文件传送的UI相比,FileTransferingViewer只是一个用于demo的简单控件。我们这里将FileTransferingViewer的源码开放给大家,大家可以在其基础上进行修改,以达到自己想要的效果(或与QQ完全一样的效果)。      

      众多其它细节,已经在ESFramework 开发手册(03) -- 文件(夹)传送 一文中作了详细介绍,这里不再赘述。大家可以参考上文和本文,然后对照源码进行研究,很容易就可以理解内部的运转流程了。 

四.源码下载 

(1)ESFramework.Demos.FileTransfer 源码

(2)ESFramework.Boosts 源码:ESFramework 增强库,里面有本文用到的FileTransferingViewer控件的源码

----------------------------------------------------------------------------------------------------------------------------------------------- 

 下载免费版本的ESFramework 以及 demo源码  

Q Q:168757008

官网:www.oraycn.com

导航

首页

官方网站

联系我们

立即咨询 

站内搜索

ESFramework 通信框架

详细说明

SDK与Demo下载

ESFramework FAQ

版本变更记录

OMCS 语音视频框架

详细说明

SDK与Demo下载

OMCS FAQ

版本变更记录

OrayTalk 企业即时通讯系统

详细说明

客户端下载

OVCS 视频会议系统

详细说明

源码下载

傲瑞实用组件

SDK下载

H5Media 纯网页音视频交互

NPusher 推流组件

MCapture 语音视频采集组件

MFile 语音视频录制组件

MPlayer 语音视频播放组件

OAUS 自动升级系统

StriveEngine 轻量级的通信引擎

傲瑞组件 FAQ

授权

授权流程

产品选购指南

授权方案说明

授权SDK使用说明

其它

支持信创国产化

SDK使用技巧

联系我们