|
From code project i got code for pause/resume to download file through ftp.
Can i get code to download file from http server with support of pause and resume.
When i downloaded code for FTP there one posted question related to HTTP. But that link is not working now.
Please help me regarding this.
|
|
|
|
|
Hi,
Can this system get files from http instead of ftp?
Thanks
|
|
|
|
|
Do not use FtpOpenFile, instead use FtpCommand:
string strSeekOffsetCMD = "TYPE I\r\nREST " + (string)pszOffset + "\r\nRETR " + strFileNameAtServer + "\r\n";<br />
<br />
bRet = ::FtpCommand(hConnect,
TRUE,
FTP_TRANSFER_TYPE_BINARY,
strSeekOffsetCMD.c_str(),
0,
&hOpenFile);
|
|
|
|
|
I had tested in my localserver using IIS.It doesn't execute properly(can not work in resume feature).
why?
|
|
|
|
|
|
Excellent Work!!!
I would like to know how to make the code work on a HTTP Server.
Thanks in Advance
|
|
|
|
|
|
But the link that u've provided is only for downloading portion.
Not for the uploading part.
|
|
|
|
|
This is a very nice article, but do you have the source code in vb6? i need it for my project.
THaNk you``~~
|
|
|
|
|
when i re-download the file from the FTP-Server, the file always get down from its head. How could I make it begin at the location which i stoped?
|
|
|
|
|
|
Affter connect successfully to a FtpServer:
FtpSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // FtpSocket is a Global Variable.
connect (FtpSocket, ...);
I tried to put a file to FtpServer by call the following put function:
int CFtp::put(char* szLocalFilename, char* szRemoteFilename)
{
// only if connected
if(!isConnected)
return FTP_ERROR_NOTCONNECTED;
// make sure local file exists
std::ifstream ifsLocalFile;
ifsLocalFile.open(szLocalFilename, std::ios_base::in | std::ios_base::binary);
if(!ifsLocalFile)
return FTP_ERROR_LOCALFILENOTFOUND;
// make sure remote path exists
std::string sPath = szRemoteFilename;
std::string sFilename; // we will do this later
std::basic_string <char>::size_type pos_first = sPath.find('/');
std::basic_string <char>::size_type pos_last = sPath.find_last_of('/');
std::string recvstring;
char recvbuffer[RECEIVE_BUFFER_SIZE];
char buffer[200];
int recvbytes;
if(pos_first==-1) // remote file contains path information
{
// no path information, so assume that this is the pure filename
sFilename = sPath;
} else {
// isolate the filename and path substring
sFilename = sPath.substr(pos_last+1,sPath.length());
if(pos_first==pos_last) // tricky part, this is a relativ path so watch out!
sPath = sPath.substr(0, pos_last+1);
else
sPath = sPath.substr(pos_first, pos_last+1);
// now try to change into this directory
sprintf(buffer, "CWD %s\n", sPath.c_str());
send(ftpSocket,buffer,static_cast<int>(strlen(buffer)),0);
if(recvStatus(ftpSocket,"250")==FTP_ERROR_FAILED)
return FTP_ERROR_REMOTEPATHNOTFOUND;
}
// paths are ok. lets switch to binary mode to be on the safe side
sprintf(buffer, "%s", "TYPE I\n");
send(ftpSocket,buffer,static_cast<int>(strlen(buffer)),0);
if(recvStatus(ftpSocket,"200")==FTP_ERROR_FAILED)
return FTP_ERROR_FAILEDTYPEI;
// now lets switch to PASV mode
sprintf(buffer, "%s", "PASV\n");
send(ftpSocket,buffer,static_cast<int>(strlen(buffer)),0);
recvbytes=recv(ftpSocket,recvbuffer,RECEIVE_BUFFER_SIZE,0);
recvstring.assign(recvbuffer,recvbytes);
if(recvstring.substr(0,3)!="227") // PASV failed
return FTP_ERROR_REMOTEPASVFAILED;
// status code 227: Entering passive mode.
// this needs to be parsed for the ip/port data channel data
// lets make a seperate scope for this task
SOCKADDR_IN server_pasv;
{
server_pasv.sin_family = AF_INET;
// lets strip the the important things from the string
std::basic_string <char>::size_type pos_find = recvstring.find('(');
recvstring = recvstring.substr(pos_find+1,recvstring.find(')')-pos_find-1);
// parse the ip into SockAddr... well this is a dirty pointer hell isnt it?
for(int i=0;i<4;i++)
{
pos_find = recvstring.find(',');
sscanf(recvstring.substr(0,pos_find).c_str(), "%d", &server_pasv.sin_addr.S_un.S_un_b.s_b1+i);
recvstring.erase(0,pos_find+1);
}
// parse the port into SockAddr
int portbyte1, portbyte2;
pos_find = recvstring.find(',');
sscanf(recvstring.substr(0,pos_find).c_str(), "%d", &portbyte1);
recvstring.erase(0,pos_find+1);
portbyte1 = portbyte1 * 256;
pos_find = recvstring.find(',');
sscanf(recvstring.substr(0,pos_find).c_str(), "%d", &portbyte2);
server_pasv.sin_port = htons(portbyte1+portbyte2);
}
// create pasvSocket
pasvSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(pasvSocket==INVALID_SOCKET)
return FTP_ERROR_PASVSOCKET;
// sync the information with the PASV socket and open the PASV data connection
if(::connect(pasvSocket,reinterpret_cast<struct sockaddr*="">(&server_pasv),sizeof(server_pasv))==SOCKET_ERROR)
{
closesocket(pasvSocket);
return FTP_ERROR_LOCALPASVFAILED;
}
// this is put, not get... so we dont need to check if data is send through this
// instead we need to announce on the ftpSocket that we want to store a file
// all commands on ftpSocket will only work after you established the pasvSocket
// otherwise your commands will be buffered till sunrise. but we took care of it already.
// remember? we already CWD'ed to the directory, so we only need the filename
/*********************************************************/
/* My question is here */
/*********************************************************/
sprintf(buffer, "STOR %s\n", sFilename.c_str());
send(ftpSocket,buffer,static_cast<int>(strlen(buffer)),0);
if(recvStatus(ftpSocket,"150")==FTP_ERROR_FAILED)
return FTP_ERROR_STORFAILED;
char sendbuffer[SEND_BUFFER_SIZE];
while(!ifsLocalFile.eof())
{
ifsLocalFile.read(sendbuffer,SEND_BUFFER_SIZE);
send(pasvSocket,sendbuffer,ifsLocalFile.gcount(),0);
}
/*************************************************************/
/* Affter "STOR" command was sent, replly code is */
/* 125 Data connection already open; tranfer starting */
/* but my file was not STORE on Server */
/*Does "while loop" not work ? I don't know what is the reason*/
/*************************************************************/
// be sure to close the pasv port! otherwise the transfer will not be finished
closesocket(pasvSocket);
if(recvStatus(ftpSocket,"226")==FTP_ERROR_FAILED)
return FTP_ERROR_TRANSFERFAILED;
// and finaly close the file
ifsLocalFile.close();
return FTP_OK;
}
Sincerely
Thangnvhl
|
|
|
|
|
I had solved above error but when i exit my program, the temp file which i save on server was lost, too. So i can't resume upload that broken file. How can i solve this problem? Could u show me?
Sincerely
Thangnvhl
|
|
|
|
|
I had solved above error but when i exit my program, the temp file which i save on server was lost, too. So i can't resume upload that broken file. How can i solve this problem? Could u show me?
Sincerely
Thangnvhl
|
|
|
|
|
I use a freeware FTPServer based on Cool FTP.
For upload resume, the REST command does nothing for me.
I use the APPE command and this work very well. With the REST command, the file was resumed but corrupted. With APPE, the file is resumed and readable.
I test this solution with a FTP server daemon on my SUN server and it works perfect.
Hope that helps.
|
|
|
|
|
Hey thanks a lot for this article also the comments here, i was able to get resume upload for serv-u work using the example given above in the comments section however for the "ABOR" and "PASV" calls was unneccessary because wininet actually drops the ftp connection and gives the error 12030, so this is what i used: std::string command="REST "+ (string)pszOffset+"\r\nSTOR "+remote_filename+ "\r\n";
I simply use the handle this call returns from ftpcommand and continue uploading the file using InternetWriteFile call. I hope this helps someone out there just wanted to share
Oh i dunno why but in some cases i did notice a Sleep(250) helped write after the FTPCommand call try this if you are getting 12111 during InternetWriteFile
|
|
|
|
|
I use rest command,but use "rest 100" or "rest 0",get same
result.I rework your program,but i get same result regardless with "rest 100" or "rest 0".
my program :
bool CPauseResumeDemoDlg::StartDownloadingHardCodedFile()
{
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
DWORD dwPacketSize =5;
DWORD dwSize, dwToRead = dwPacketSize * 1024;
PBYTE pBuffer = new BYTE[dwPacketSize * 1024];
double dFileSize = 352256;
double dOffsetToSeek =0;
HINTERNET hConnect = NULL;
HINTERNET hOpen = NULL;
HINTERNET hOpenFile = NULL;
BOOL bRet = FALSE;
BOOL bInComplete = FALSE;
INTERNET_PORT nServerPort =21;
FILE * pFile = NULL;
string strTmpFileName = "Temp_find-ls.txt.gz";
string strFileNameAtLocalMachine= "find-ls.txt.gz";
string strFileNameAtServer= "/s.txt";
CString strStaus;
double nTripsToServerCnt;
int nTotalSpan = 100;
DWORD dwBytesWrrittenToFile =0;
nTripsToServerCnt = ceil(dFileSize / ((NKBYTE * 1024)*1.0));
if(nTripsToServerCnt ==0)
nTripsToServerCnt =1;
while(nTripsToServerCnt > nTotalSpan)
{
nTotalSpan *= 10;
}
DeleteFile(strFileNameAtLocalMachine.c_str());
m_ProgressCtl.SetRange(0,nTotalSpan);
//m_ProgressCtl.SetPos(1);
strStaus.Format("Initializing WinInet..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
hOpen = InternetOpen("PauseResumeDemo",INTERNET_OPEN_TYPE_PRECONFIG ,NULL, NULL, NULL);
if(!hOpen)
{
return false;
}
DWORD dwContext = 123;
strStaus.Format("Connecting to server..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if ( !(hConnect = InternetConnect( hOpen, "localhost" , nServerPort, NULL, NULL, INTERNET_SERVICE_FTP, 0 , 0) ) )
{
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
strStaus.Format("Finding out if this server supoprts Pause & Resume..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(FindPauseResumeSupported(hConnect))
{
strStaus.Format("Pause & Resume Supported..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
else
{
strStaus.Format("Pause & Resume not Supported..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
double dCurrentFileSize;
if(IfLocalFileExist(strTmpFileName.c_str(), &dCurrentFileSize))
{
dOffsetToSeek = dCurrentFileSize;
}
dOffsetToSeek=40;
if(dOffsetToSeek >0)
{
strStaus.Format("Sending REST...");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
//Seek to the file first
char pszOffset[30];
HINTERNET hResponse;
ltoa(dOffsetToSeek, pszOffset, 10);
//sprintf(pszOffset,"%ld", dOffsetToSeek);
string strSeekOffsetCMD = "REST " + (string)pszOffset;
bRet =FtpCommand(hConnect, // WinInet Connection handle
FALSE, // No, I don't expect a response
FTP_TRANSFER_TYPE_BINARY, // I'm receiving ASCII
"REST 6000",//strSeekOffsetCMD.c_str(), // This is the FTP command I am passing
0, // No context needed
&hResponse); // The handle to read the response
if (!bRet)
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
}
}
hOpenFile = ::FtpOpenFile(hConnect,strFileNameAtServer.c_str(), GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 1);
// DWORD dd=InternetSetFilePointer(hOpenFile,100,NULL,FILE_BEGIN,0);
if(hOpenFile == NULL)
{
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if ( !(pFile = fopen (strTmpFileName.c_str(), "ab" ) ) )
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if(dOffsetToSeek >=0)
{
strStaus.Format("Seeking to local file...");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
int n = fseek(pFile, dOffsetToSeek, SEEK_SET);
}
dwBytesWrrittenToFile = dOffsetToSeek;
GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE);
do
{
PUMPMESSAGE();
//Intentional delay so that user get chance to hit stop button
Sleep(100);
strStaus.Format("Sending RETRIVE..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(m_bStopped)
{
strStaus.Format("Stopped..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
AfxMessageBox("Download aborted\nThere is an incomplete temp file 'Temp_find-ls.txt.gz' at current directory. Don't delete it just check it out. It has useful data downloaded so far...\nOnce you are done click Start again, now download will start from exact location where it left off");
m_bStopped = FALSE;
bInComplete = TRUE;
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
break;
}
if (!InternetReadFile (hOpenFile, (LPVOID)pBuffer, dwToRead, &dwSize) )
{
fclose (pFile);
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if (!dwSize)
{
m_ProgressCtl.SetPos(100);
CString strTmpPercentage;
strTmpPercentage.Format("Percentage Completed:%d%%", 100);
GetDlgItem(IDC_STATIC_PERCENTAGE)->SetWindowText(strTmpPercentage);
break; // Condition of dwSize=0 indicate EOF. Stop.
}
else
{
fwrite(pBuffer, sizeof (char), dwSize , pFile);
Sleep(2000);
dwBytesWrrittenToFile = dwBytesWrrittenToFile + dwSize;
int nPercentageComplete = (int)floor(((dwBytesWrrittenToFile) * 100)/dFileSize);
CString strTmpPercentage;
strTmpPercentage.Format("Percentage Completed:%d%%", nPercentageComplete);
GetDlgItem(IDC_STATIC_PERCENTAGE)->SetWindowText(strTmpPercentage);
//m_pMainFrame->m_ProgressCtl.SetBkColor(RGB(0, 255, 0));
int nLower, nUpper;
m_ProgressCtl.GetRange(nLower, nUpper );
m_ProgressCtl.SetPos(((nUpper-nLower)/100) * nPercentageComplete);
}
} // do
while (TRUE);
fflush (pFile);
fclose (pFile);
delete [] pBuffer;
if(!bInComplete)
{
strStaus.Format("Renaming file at local machine..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(!MoveFile(strTmpFileName.c_str(), strFileNameAtLocalMachine.c_str() ))
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
}
strStaus.Format("Done..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
if(!bInComplete)
{
AfxMessageBox("File has downloaded..");
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
}
if(hConnect)
InternetCloseHandle(hConnect);
if(hOpen)
InternetCloseHandle(hOpen);
if(hOpenFile)
InternetCloseHandle(hOpenFile);
return TRUE;
}
thank you
|
|
|
|
|
I use rest command,but use "rest 100" or "rest 0",get same
result.I rework your program,but i get same result regardless with "rest 100" or "rest 0".
my program :
bool CPauseResumeDemoDlg::StartDownloadingHardCodedFile()
{
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
DWORD dwPacketSize =5;
DWORD dwSize, dwToRead = dwPacketSize * 1024;
PBYTE pBuffer = new BYTE[dwPacketSize * 1024];
double dFileSize = 352256;
double dOffsetToSeek =0;
HINTERNET hConnect = NULL;
HINTERNET hOpen = NULL;
HINTERNET hOpenFile = NULL;
BOOL bRet = FALSE;
BOOL bInComplete = FALSE;
INTERNET_PORT nServerPort =21;
FILE * pFile = NULL;
string strTmpFileName = "Temp_find-ls.txt.gz";
string strFileNameAtLocalMachine= "find-ls.txt.gz";
string strFileNameAtServer= "/s.txt";
CString strStaus;
double nTripsToServerCnt;
int nTotalSpan = 100;
DWORD dwBytesWrrittenToFile =0;
nTripsToServerCnt = ceil(dFileSize / ((NKBYTE * 1024)*1.0));
if(nTripsToServerCnt ==0)
nTripsToServerCnt =1;
while(nTripsToServerCnt > nTotalSpan)
{
nTotalSpan *= 10;
}
DeleteFile(strFileNameAtLocalMachine.c_str());
m_ProgressCtl.SetRange(0,nTotalSpan);
//m_ProgressCtl.SetPos(1);
strStaus.Format("Initializing WinInet..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
hOpen = InternetOpen("PauseResumeDemo",INTERNET_OPEN_TYPE_PRECONFIG ,NULL, NULL, NULL);
if(!hOpen)
{
return false;
}
DWORD dwContext = 123;
strStaus.Format("Connecting to server..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if ( !(hConnect = InternetConnect( hOpen, "localhost" , nServerPort, NULL, NULL, INTERNET_SERVICE_FTP, 0 , 0) ) )
{
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
strStaus.Format("Finding out if this server supoprts Pause & Resume..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(FindPauseResumeSupported(hConnect))
{
strStaus.Format("Pause & Resume Supported..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
else
{
strStaus.Format("Pause & Resume not Supported..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
double dCurrentFileSize;
if(IfLocalFileExist(strTmpFileName.c_str(), &dCurrentFileSize))
{
dOffsetToSeek = dCurrentFileSize;
}
dOffsetToSeek=40;
if(dOffsetToSeek >0)
{
strStaus.Format("Sending REST...");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
//Seek to the file first
char pszOffset[30];
HINTERNET hResponse;
ltoa(dOffsetToSeek, pszOffset, 10);
//sprintf(pszOffset,"%ld", dOffsetToSeek);
string strSeekOffsetCMD = "REST " + (string)pszOffset;
bRet =FtpCommand(hConnect, // WinInet Connection handle
FALSE, // No, I don't expect a response
FTP_TRANSFER_TYPE_BINARY, // I'm receiving ASCII
"REST 6000",//strSeekOffsetCMD.c_str(), // This is the FTP command I am passing
0, // No context needed
&hResponse); // The handle to read the response
if (!bRet)
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
}
}
hOpenFile = ::FtpOpenFile(hConnect,strFileNameAtServer.c_str(), GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 1);
// DWORD dd=InternetSetFilePointer(hOpenFile,100,NULL,FILE_BEGIN,0);
if(hOpenFile == NULL)
{
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if ( !(pFile = fopen (strTmpFileName.c_str(), "ab" ) ) )
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if(dOffsetToSeek >=0)
{
strStaus.Format("Seeking to local file...");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
int n = fseek(pFile, dOffsetToSeek, SEEK_SET);
}
dwBytesWrrittenToFile = dOffsetToSeek;
GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE);
do
{
PUMPMESSAGE();
//Intentional delay so that user get chance to hit stop button
Sleep(100);
strStaus.Format("Sending RETRIVE..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(m_bStopped)
{
strStaus.Format("Stopped..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
AfxMessageBox("Download aborted\nThere is an incomplete temp file 'Temp_find-ls.txt.gz' at current directory. Don't delete it just check it out. It has useful data downloaded so far...\nOnce you are done click Start again, now download will start from exact location where it left off");
m_bStopped = FALSE;
bInComplete = TRUE;
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
break;
}
if (!InternetReadFile (hOpenFile, (LPVOID)pBuffer, dwToRead, &dwSize) )
{
fclose (pFile);
CString strMsg;
string strReposeFromServer;
GetLastResponse(strReposeFromServer);
strMsg.Format("Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
AfxMessageBox(strMsg, MB_OK);
return false;
}
if (!dwSize)
{
m_ProgressCtl.SetPos(100);
CString strTmpPercentage;
strTmpPercentage.Format("Percentage Completed:%d%%", 100);
GetDlgItem(IDC_STATIC_PERCENTAGE)->SetWindowText(strTmpPercentage);
break; // Condition of dwSize=0 indicate EOF. Stop.
}
else
{
fwrite(pBuffer, sizeof (char), dwSize , pFile);
Sleep(2000);
dwBytesWrrittenToFile = dwBytesWrrittenToFile + dwSize;
int nPercentageComplete = (int)floor(((dwBytesWrrittenToFile) * 100)/dFileSize);
CString strTmpPercentage;
strTmpPercentage.Format("Percentage Completed:%d%%", nPercentageComplete);
GetDlgItem(IDC_STATIC_PERCENTAGE)->SetWindowText(strTmpPercentage);
//m_pMainFrame->m_ProgressCtl.SetBkColor(RGB(0, 255, 0));
int nLower, nUpper;
m_ProgressCtl.GetRange(nLower, nUpper );
m_ProgressCtl.SetPos(((nUpper-nLower)/100) * nPercentageComplete);
}
} // do
while (TRUE);
fflush (pFile);
fclose (pFile);
delete [] pBuffer;
if(!bInComplete)
{
strStaus.Format("Renaming file at local machine..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
if(!MoveFile(strTmpFileName.c_str(), strFileNameAtLocalMachine.c_str() ))
{
CString strMsg;
strMsg.Format("Error:%d", GetLastError());
AfxMessageBox(strMsg, MB_OK);
}
strStaus.Format("Done..");
GetDlgItem(IDC_STATIC_STATUSNEW)->SetWindowText(strStaus);
}
if(!bInComplete)
{
AfxMessageBox("File has downloaded..");
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
}
if(hConnect)
InternetCloseHandle(hConnect);
if(hOpen)
InternetCloseHandle(hOpen);
if(hOpenFile)
InternetCloseHandle(hOpenFile);
return TRUE;
}
thank you
|
|
|
|
|
This code does not work on IIS and Serv-U.
Because based on RFC 959 we must send REST command and then immediately RETR.
With WinInet we have REST, PASV, TYPE I, RETR.
So, at any normal ftp server this resuming wouldn't work.
|
|
|
|
|
I too have failed to get this to work on the IIS 5.1 FTP server. This server is supposed to happily support the REST command, and answers "350 Restarting at XXX." when commanded "REST XXX"; however the subsequent attempt to retrieve a file starts from the beginning of the file, possibly because of the reason you gave.
Does anybody know how to get the REST command to work on IIS ?
Dan Ababei
|
|
|
|
|
Hi!
I just can´t get it to work on other servers than ftp.gnu.org
Even if I upload the file you´re using it doesn´t work.
When resuming, the local file is appended with, as it seems, the entire
remote file, which makes the local file much larger than it should be.
The servers I´ve tested it on, they all support resuming. (ie ftp.microsoft.com)
The REST command which is sent to the server before the download starts seems to work fine,
after sending the command I recieve:
"Error Description:350 Restarting at 66560"
What am I doing wrong?
/Jonatan
|
|
|
|
|
Hi, sorry for the delay in reply.
Well I have tried with a lot of servers and it seems to be working in most of the cases I have not tried particularly at ftp.microsoft.com but you have to the source code. Why don't you try to debug the code and find out if there is something wrong with the code. I am sure there is nothing wrong with the logic as it is working with most of other servers, there could be differences in responses at Microsoft server itself which will be interesting to know.
Try debugging it.
Thanks!!
Narendra Chandel
__NarendraC
|
|
|
|
|
Hi!
Thanks for answering!
Well, I´ve tried to debug it for a couple of days but I can´t come up with a solution.
I´m pretty sure that the REST command, or at least what comes after it, is the problem.
After sending the rest command to my server I get the following respone:
350 Restarting at 112640
Send STOR or RETR to initiate transfer
The servers response seems OK.
Then the followinf happens after sending the REST command:
I open the remote file using ::FtpOpenFile()
Then the server sends me the followingresponse:
200 TYPE is now 8-bit binary
200 PORT command successful
213 384937
150-Connecting to 217.xxx.xxx.xx:34725
150 375.9 kbytes to download
384937 byte which is 375.9 kbytes is the filesize.
It tells me it´s gonna send me the whole file from the beginning.
This can´t be right, because earlier it told me it was starting
the download at 112640 byte.
The first response from server tells me to send the RETR command to initiate transfer,
isn´t this what the ::FtpOpenFile() or ::InternetReadFile() do?
I´ve heard that some servers need to be put in block mode
before sending the RETR command. This is done by sending the command "MODE B" to the server.
Anyway, this is just something I´ve heard and I don´t know if it´s correct or how to implement it.
Any clues?
Thanks!
/Jonatan Dahl
|
|
|
|
|
I have found the same problem.We can use REST and then use RETR or STORE command to resume file transfer,but if we use InternetReadFile() or InternetWriteFile() to resume the file transfer,the final file will have different size then the original file.For example,if I try to download a file
100k from a ftp,and I abort the file transfer as the file is 50k downloaded,and then I resume.after the file transfer is completed,the file I
get is much bigger then 100k.I test this with serv-u.
|
|
|
|
|
I have been having the same exact problem. In reading the email thread it appears to confirm what I have suspected. That the WinInet high level functions do not internally support the REST command by virtue of the fact that when you do the Open it resets the port connection, invalidating the any previous REST commands. So, the solution seems to be to invoke my own RETR without using the WinInet functions. With that in mind, does anyone know where I can find an example of how to use FTPCommand with the RETR verb?
Thank you.
|
|
|
|
|