.NET的类库中有一些操作FTP的类,不过用起来都没不是很直观,需要一些封装才比较好用,在sourceforge上找到一个人写的FTPClient,这个类对.NET的类库System.Net.Sockets进行了一定的封装,主要是使用了其中的类TcpClient,通过这个类发送一些FTP协议定义的命令,比如LIST,RETR等,从FTP服务器上获取相应的信息,该类在http://sourceforge.net/projects/dotnetftpclient/,它这个类本身没有写断点续传的部分,只要在上面增加几行代码就可以实现断点续传了。
断点续传分为断点下载和上传两部分,在FTP协议中定义了用REST指定开始下载或上传的文件的位置。
先说一下下载断点续传部分:
在这个Solution中,主要代码在类FTPConnection中,下载是通过该类的GetFile实现的,原实现中,它在打开文件的时候用的是Create,这样每次就会创建一个新的文件了,为了断点续传我们需要改成Append,这样在下载的时候就可以接着来了,如下所示:
Code
public virtual void GetFile(string remoteFileName, string localFileName, FTPFileTransferType type)
{
FileStream fs = new FileStream(localFileName, FileMode.Append);
GetStream(remoteFileName, fs, type);
fs.Close();
}
然后需要修改一下它的GetStream方法,原实现中直接向FTP服务器发送了RETR命令,这样它就从头开始下载文件了,如果想从断点开始下载,需要在发送RETR命名之前,通过REST命令告诉FTP服务器,你想从哪里开始接着下载,改成如下所示的代码:
Code
//Begin 增加断点续传功能 发送REST命令给FTP服务器
tempMessageList = new ArrayList();
tempMessageList = SendCommand("REST "+stream.Length);
returnValue = GetMessageReturnValue((string)tempMessageList[0]);
if (returnValue != 350)
{
throw new Exception((string)tempMessageList[0]);
}
//End 增加断点续传功能 发送REST命令给FTP服务器
tempMessageList = new ArrayList();
tempMessageList = SendCommand("RETR " + remoteFileName);
returnValue = GetMessageReturnValue((string)tempMessageList[0]);
if(!(returnValue == 150 || returnValue == 125))
{
throw new Exception((string)tempMessageList[0]);
}
其中REST后面跟的参数stream.Length是下载到本地对应的文件的长度,经过这样修改,就可以接着之前下载的内容继续下载了。
上传断点续传部分
根据FTP协议的定义,断点上传之前也需要发送REST命令告诉FTP服务器你要从哪里开始继续发送数据,跟一般的上传不同的是,一般的上传通过命令STOR,而如果想要支持断点续传需要通过命令APPE才行,另外还有就是需要先获取FTP服务器上的文件上传到什么程度了,这个可以通过这个类的XDIR获取到FTP服务器上某个目录下的文件列表,并得到文件的大小,跟要上传的文件比对,文件名相同就继续上次的上传,可以在FTPConnection类里新增一个SendStream方法,主要修改的地方就是发送REST和APPE命令,其他的地方可以不用修改。
Code
//Send REST 命令
tempMessageList = SendCommand("REST " + startPosition);
returnValue = GetMessageReturnValue((string)tempMessageList[0]);
if (returnValue != 350)
{
throw new Exception((string)tempMessageList[0]);
}
tempMessageList = SendCommand("APPE " + remoteFileName);
returnValue = GetMessageReturnValue((string)tempMessageList[0]);
if (!(returnValue == 150 || returnValue == 125))
{
throw new Exception((string)tempMessageList[0]);
}
其中REST命令的startPosition参数是从FTP服务器上获取到的以前上传的文件的大小。
另外,这个类不支持中文,可以修改一下这个类的ReadLine方法,把编码从ASCII改成GB2312就可以了。
tmpMes += Encoding.GetEncoding("GB2312").GetString(buffer, 0, bytes);
差不多就这些了。