FTP断点下载
断点下载原理实现流程
断点下载程序流程图
断点下载程序代码
bool CSelfFtpUpDownloaderDlg::FtpDownContinue(CString FilePath,CString FileName)
{
CFile localFile;
if(!localFile.Open(FilePath,CFile::modeWrite|CFile::modeNoTruncate|CFile::modeCreate|CFile::shareDenyNone))
{
AfxMessageBox("CFile失败!");
return false;
}
//获取本地文件大小
CFileStatus fileStatus;
localFile.GetStatus(fileStatus);
long long m_nFileTransSize=fileStatus.m_size;
long long filesz = m_nFileTransSize;
CString fsize;
fsize.Format("%d",m_nFileTransSize);
//本地文件指针指向末尾
localFile.SeekToEnd();
CString pszOffset;
pszOffset.Format("%d",m_nFileTransSize);
CString strSeekOffsetCMD;
DWORD dwError;
TCHAR databuf1[200];
DWORD size=200;
//以二进制传输
pFtpConnection->Command("TYPE I",CFtpConnection::CmdRespNone);
//前期测试回传码
InternetGetLastResponseInfo(&dwError,databuf1,&size);
m_Diary.SetWindowTextA(databuf1);
pFtpConnection->Command("PASV",CFtpConnection::CmdRespNone);
InternetGetLastResponseInfo(&dwError,databuf1,&size);
m_Diary.SetWindowTextA(databuf1);
pFtpConnection->Command("PASV",CFtpConnection::CmdRespNone);
InternetGetLastResponseInfo(&dwError,databuf1,&size);
m_Diary.SetWindowTextA(databuf1);
int dataPort=ParsePasv(databuf1);
pFtpConnection->Command("REST "+pszOffset,CFtpConnection::CmdRespNone);
InternetGetLastResponseInfo(&dwError,databuf1,&size);
m_Diary.SetWindowTextA(databuf1);
strSeekOffsetCMD="RETR /"+ FileName;
pFtpConnection->Command(strSeekOffsetCMD,CFtpConnection::CmdRespNone);
InternetGetLastResponseInfo(&dwError,databuf1,&size);
m_Diary.SetWindowTextA(databuf1);
//创建客户端套接字,并检测是否创建成功
int sockCli;
sockCli = socket(AF_INET, SOCK_STREAM, 0);
//创建一个地址信息结构体,并对其内容进行设置
struct sockaddr_in addrSer;
addrSer.sin_family = AF_INET; //使用AF_INET协议族
addrSer.sin_port = htons(dataPort); //设置端口号
addrSer.sin_addr.s_addr = inet_addr(FtpIP); //设置服务器ip
//创建一个与服务器的连接,并检测连接是否成功
int ret = connect(sockCli,(struct sockaddr*)&addrSer, sizeof(struct sockaddr));
if( ret == SOCKET_ERROR )
{
AfxMessageBox("socket失败!");
return FALSE;
}
//下载文件
int len;
char buffer[1024*16] = {0};
DWORD nBufSize = 1024*16;
m_Prog.SetRange32(0,szFile);//设置进度条的范围
m_Prog.SetPos(m_nFileTransSize);//更新进度条位置
m_stop.EnableWindow(true);
//获取当前时间
COleDateTime dlStart = COleDateTime::GetCurrentTime();
COleDateTimeSpan dlElapsed;
CString KBsec,Perc;
long long kbsec = 0;
DWORD nperc; // 进度百分比
m_Diary.SetWindowTextA("正在断点下载"+FileName+"...");
do
{
len = recv(sockCli,buffer,nBufSize,0);
if(len<0)
break;
localFile.Write(buffer,len);
m_nFileTransSize += len;
m_Prog.SetPos(m_nFileTransSize);//更新进度条位置
nperc = m_nFileTransSize * 100 / szFile;
Perc.Format("%d", nperc);
m_PerEdit.SetWindowTextA(Perc+"%");
// 根据开始时间与当前时间比较,获取秒数
dlElapsed = COleDateTime::GetCurrentTime() - dlStart;
kbsec = (m_nFileTransSize-filesz)*1.6/1024/dlElapsed/1024/1024/100;
KBsec.Format("%d",(ULONGLONG)kbsec); // 格式化下载速度(MB/秒)
m_Speed.SetWindowTextA(KBsec+"MB/s");
MSG msg; //更新
while(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(m_Flag)//暂停按下
{
pInternetSession->Close(); //关闭废弃的会话
this->ConnectFtp(); //保持持续会话
return false;
}
}while( len > 0 );
localFile.Close();
m_Diary.SetWindowTextA("断点下载"+FileName+"成功");
return true;
}
UINT32 CSelfFtpUpDownloaderDlg::ParsePasv(char *buf)
{
char *p = strchr(buf,'(');
p++; //跳过‘(’
char *q = strchr(buf,')');
if( !p || !q ) return -1;
*(p + (q - p)) = '/0';
UINT32 port = 1;
p = strchr(p,',');
p++;
p = strchr(p,',');
p++;
p = strchr(p,',');
p++;
p = strchr(p,',');
p++;
port = atol(p) * 256 ;
//AfxMessageBox(p);
CString port1;
port1.Format("%d",port);
//AfxMessageBox(port1);
p = strchr(p,',');
p++;
port += atol(p)/10;
//AfxMessageBox(p);
port1.Format("%d",port);
//AfxMessageBox(port1);
return port;
}
断点下载演示动图
FTP断点上传
断点上传原理实现流程
断点上传程序流程图
断点上传程序代码
bool CSelfFtpUpDownloaderDlg::FtpTransProc(CString FilePath,CString FileName)
{
CString m_ftpPath = FileName;
CFile localFile; //要上传的本地文件//FilePath:路径+文件名
DWORD nRet = localFile.Open(FilePath,CFile::modeRead|CFile::shareDenyRead);
if(!nRet)
{
OutputDebugString("open file error");
return false;
}
//获取文件大小,设置续传文件的位置
long long m_nFileTransSize;
long long pos;
CString KBsec,Perc;
long long kbsec = 0;
DWORD nperc; // 进度百分比
m_nFileTransSize = GetFtpFileSize(pFtpConnection,m_ftpPath);
pos = m_nFileTransSize;
DWORD filesize = localFile.GetLength();//记录本地文件大小
m_Prog.SetRange32(0,filesize);//设置进度条的范围
m_Prog.SetPos(m_nFileTransSize);//设置当前进度条位置
localFile.Seek(m_nFileTransSize,CFile::begin);
///pFtpConnection->CreateDirectory(m_ftpPath);
//是指路径:如FTP://file1/file2.rar 则是"file1//file2.rar"
CInternetFile *pInetFile = NULL;
pInetFile=pFtpConnection->Command("APPE " +m_ftpPath,CFtpConnection::CmdRespWrite);
DWORD dwError;
TCHAR databuf1[200];
DWORD size = 200;
//前期测试回传码
InternetGetLastResponseInfo(&dwError, databuf1, &size);
AfxMessageBox("APPE");
AfxMessageBox(databuf1);
DWORD len;
char buffer[1024*16] = {0};
DWORD nBufSize = 1024*16;
//获取当前时间
COleDateTime dlStart = COleDateTime::GetCurrentTime();
COleDateTimeSpan dlElapsed;
//读写文件
while(len=localFile.Read(buffer,nBufSize))
{
pInetFile->Write(buffer,len);
m_nFileTransSize += len;
m_Prog.SetPos(m_nFileTransSize);//更新进度条位置
nperc = m_nFileTransSize * 100 / filesize;
Perc.Format("%d", nperc);
m_PerEdit.SetWindowTextA(Perc+"%");
// 根据开始时间与当前时间比较,获取秒数
dlElapsed = COleDateTime::GetCurrentTime() - dlStart;
kbsec = (m_nFileTransSize - pos)*1.6/1024/dlElapsed/1024/1024/100;
KBsec.Format("%d",(ULONGLONG)kbsec); // 格式化下载速度(MB/秒)
m_Speed.SetWindowTextA(KBsec+"MB/s");
MSG msg; //更新
while(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(m_Flag)//按下暂停键
{
pInternetSession->Close(); //关闭废弃的会话
this->ConnectFtp(); //保持持续会话
return false;
}
}
localFile.Close();
m_Diary.SetWindowTextA("断点续传"+FileName+"成功");
return true;
}
断点上传演示动图