网上搜到的在 Windows 中对 FTP 断点上传的方法都是使用 CSocket 来做的,其实使用 WinINet 中带有的类就可以实现断点上传了。直接看代码。
void CWebFtpClientCtrl::fileUpload(LPCTSTR serverName, INTERNET_PORT port, LPCTSTR userName, LPCTSTR password, LPCTSTR localFileName, LPCTSTR serverFileName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CInternetSession InetSession;
CFtpConnection *ftp=NULL;
try{
ftp = InetSession.GetFtpConnection(serverName, userName, password, port, 1); // 这里的最后一个参数是把模式设置为 PASV,否则不能续传
}catch(CInternetException *pEx){
MessageBox("不能连接服务器!请确认服务已开启","错误");
InetSession.Close();
if(ftp != NULL)
{
delete ftp;
ftp = NULL;
}
pEx->Delete();
return;
}
CInternetFile *serverFile;
// 取服务器文件大小,不需要手工使用 CSocket 来发送 SIZE 命令来获取
ULONGLONG size = 0;
CFtpFileFind finder(ftp);
if (finder.FindFile(serverFileName))
{
finder.FindNextFile();
size = finder.GetLength();
}
if (size > 0) // 服务器已经存在就断点续传
{
CString str;
str.Format("REST %ld\r\n", size); // 发送 Restore 命令
ftp->Command(str);
serverFile = ftp->OpenFile(serverFileName, GENERIC_WRITE); // 准备写入远程的文件
CFile localFile; // 打开本地的文件之后,定位到需要续传的位置
localFile.Open(localFileName, 0);
localFile.Seek(size, 0);
}
// 把需要续传的部分推向服务器
const ULONGLONG bufLen = 2048;
char buffer[bufLen];
while(localFile.Read(buffer, bufLen))
{
serverFile->Write(buffer, bufLen);
// TODO: 数据比缓冲区长度还短的时候
}
serverFile->Close();
localFile.Close();
// 善后工作
dlgPrompt->DestroyWindow();
ftp->Close();
InetSession.Close();
if(ftp != NULL)
{
delete ftp;
ftp = NULL;
}
delete dlgPrompt;
}