Click here to Skip to main content
12,699,531 members (33,078 online)
Click here to Skip to main content
Add your own
alternative version


82 bookmarked

Pause & Resume at Protocol level. (You can implement it in any language)

, 9 Oct 2002
Rate this:
Please Sign up or sign in to vote.
Ever wondered how some of the popular download tools have capability to break download in middle, disconnect from net, later reconnect and restart file transfer from exact point they left earlier.

Sample Image - pauseresume.jpg


Ever wondered how some of the popular download tools and FTP clients have capability to break download in middle, disconnect from net, later reconnect and restart file transfer from exact point they left earlier. I wanted to do the same for a FTP client I wrote (check this out) but had no clue how??? There is no direct API support from Microsoft. I found some third party support but that costs money. So I have searched here and there and wrote my own. My way may not represents a standard, but this one work with almost every FTP server.

I have been reading stuff from this website in past and thought it is time to pay back. So I decided to put things together and write my first article. Feel free to ask me questions in case I could not do my job well :). Also I prepared a working C++ sample to demonstrate my idea. You can write it in any language of your own choice as long you have some way to send & receive FTP commands to server. Feel free to use or change this sample in any way you like a credit is appreciated but not required if you reuse the code.


Some theory to warm up

Most of the FTP server around these days supports RESTART (REST) command. (Check this W3C link to learn more about other FTP commands). Purpose of REST command is to basically tell FTP server to set its marker at which the file transfer has to be restarted.

Programmatically starting download pausing and then restarting again

Let say for example you are downloading a file:

  1. Typically send a RETRIEVE (RETR) command for file to the FTP server to start download. Store data received from server to a temp file for example So any time download is aborted, size of temp file is the actual useful data transferred so far of
  2. Let say all of a sudden ISP connection is broken or FTP server is down or your FTP client crashed or you manually stopped the download.
  3. Now Next time when you want to restart download, read the size of temp file (i.e. useful data downloaded so far), and seek to the end of the temp file so further download will append the data from end.
  4. Now send a REST command to FTP server and pass the file size of temp file as parameter. (a typical syntax would be REST 250 if size of temp file was 250). FTP server will send a response stating something like "Restarting from byte 250..".
  5. Now you can send RETRIEVE (RETR) again for file and FTP server will start sending data from byte offset 251 onwards.
  6. Now it is your responsibility to append the data coming from server to the incomplete file and you are all set.
  7. Once the transfer is complete rename the temp file to the actual file name on WINDOWS using C++ it should typically look like RenameFile(,; Done.

Programmatically starting upload pausing and then restarting again

For upload scenario, conceptually you do something similar but different points are..

  1. Send a STORE command first.
  2. Connection breaks.
  3. Read the size of incomplete temp file at FTP server by either sending SIZE or use your favorite way there could be many.
  4. Seek to the local file up to the size received from server, so you will start reading and sending data from the location just after.
  5. Send a REST command. So FTP server will set the marker to start appending data from the location passed in REST command.
  6. Send STORE again.
  7. Once done rename the file at FTP server a typical winInet funcion would be FtpRenameFile(hConnect,,, or use your favorite way like directly sending RENAME FROM (RNFR) & RENAME TO (RNTO) which are obviously faster, then WinInet.
  8. Done.

Programmatically determining if a particular FTP server supports Pause & Resume

Three simple steps

  1. Once connected to FTP server try sending a REST command with 0 ( zero ) as argument.
  2. If commands fail or server return something like command is not supported. That means this server doesn't support Pause and Resume.
  3. If FTP server return a response stating something like "Restarting from byte 0" that means server supports Pause & Resume

Now if you just started writing code you may have question, how to send these commands the FTP server. Answer is so many ways. Raw socket is one, WinInet is another. In my sample code I have utilized WinInet's API FtpCommand to send direct commands to FTP server.

About the C+ Sample

I have written this sample in VC++, to demonstrate how we can use WinInet to implement pause and resume, don't look at my coding style for purpose of code review just take it as a sample which I wrote in less then an hour. The code is barely reusable only the idea is reusable, so I kept no restriction on it's usage. First build and run the sample don't forget to link it against the wininet.lib zipped with sample.

This sample demonstrate the download pause and restart download scenario. When you run the sample click the download button to start the download and note the progress bar showing the progress. Stop in between and restart again. Note the download will restart from the location it left off last time. Click Start and as many times as you want until the download is finished. Note that download is hard coded from, and file is always find-ls.txt.gz from root directory.

Sample is self explanatory but still if you have any question ask me I will answer as per my best knowledge.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Narendra Chandel
Web Developer
United States United States
To know more about Narendra's professional work one can check his profile below:

You may also be interested in...


Comments and Discussions

QuestionHow to make the Code work on a HTTP Server Pin
sureskoleti24-Jul-09 3:57
membersureskoleti24-Jul-09 3:57 
Questionhow about http Pin
monsieur_jj30-Apr-08 20:54
membermonsieur_jj30-Apr-08 20:54 
GeneralIt works for me Pin
1thing26-Sep-07 8:11
member1thing26-Sep-07 8:11 
QuestionDoesn't support IIS Pin
msrameshkumar18-Apr-07 1:39
membermsrameshkumar18-Apr-07 1:39 
Questionwhy not? Pin
elfederico4-Feb-07 7:06
memberelfederico4-Feb-07 7:06 
QuestionHow to make the Code work on a HTTP Server Pin
prabu.s2-Feb-06 23:38
memberprabu.s2-Feb-06 23:38 
AnswerRe: How to make the Code work on a HTTP Server Pin
Yuvi Panda23-Apr-06 23:42
memberYuvi Panda23-Apr-06 23:42 
GeneralRe: How to make the Code work on a HTTP Server Pin
KhinLLK18-Mar-07 17:24
memberKhinLLK18-Mar-07 17:24 
Questionsource code in vb6? Pin
SewH25-Jan-06 21:06
memberSewH25-Jan-06 21:06 
QuestionDownload bedug?? Pin
wang-yuan-sheng19-Oct-05 1:44
memberwang-yuan-sheng19-Oct-05 1:44 
Questionit doesn't work, why? Pin
liuty200626-May-05 19:22
memberliuty200626-May-05 19:22 
QuestionMy question: Unknow error ??? Pin
thangnvhl28-Apr-05 16:29
memberthangnvhl28-Apr-05 16:29 
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

// make sure local file exists
std::ifstream ifsLocalFile;, std::ios_base::in | std::ios_base::binary);

// 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);
sPath = sPath.substr(pos_first, pos_last+1);

// now try to change into this directory
sprintf(buffer, "CWD %s\n", sPath.c_str());
// paths are ok. lets switch to binary mode to be on the safe side
sprintf(buffer, "%s", "TYPE I\n");

// now lets switch to PASV mode
sprintf(buffer, "%s", "PASV\n");
if(recvstring.substr(0,3)!="227") // PASV failed

// 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? Wink | ;)
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);

// parse the port into SockAddr
int portbyte1, portbyte2;
pos_find = recvstring.find(',');
sscanf(recvstring.substr(0,pos_find).c_str(), "%d", &portbyte1);
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

// 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)

// 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());

char sendbuffer[SEND_BUFFER_SIZE];

/* 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


// and finaly close the file
return FTP_OK;

AnswerRe: My question: Unknow error ??? Pin
thangnvhl17-May-05 17:41
sussthangnvhl17-May-05 17:41 
AnswerRe: My question: Unknow error ??? Pin
thangnvhl17-May-05 17:41
sussthangnvhl17-May-05 17:41 
GeneralUpload Pin
Krouer23-May-04 22:26
memberKrouer23-May-04 22:26 
GeneralServ-U Upload Resume Pin
seymen13-Mar-04 20:49
memberseymen13-Mar-04 20:49 
Generalask rest command?why not Pin
smalldragon7713-Apr-03 23:23
membersmalldragon7713-Apr-03 23:23 
Generalask rest command?why not Pin
ffffffffffffffffffffffffffff13-Apr-03 23:21
memberffffffffffffffffffffffffffff13-Apr-03 23:21 
GeneralIt does not work on standart FTP server Pin
Dmitry Rudnitsky8-Mar-03 4:39
memberDmitry Rudnitsky8-Mar-03 4:39 
GeneralRe: It does not work on standart FTP server Pin
vasilica9-Apr-03 5:07
membervasilica9-Apr-03 5:07 
GeneralCan´t get it to work on other servers Pin
Jonatan Dahl11-Feb-03 8:55
memberJonatan Dahl11-Feb-03 8:55 
GeneralRe: Can´t get it to work on other servers Pin
Narendra Chandel18-Feb-03 20:19
memberNarendra Chandel18-Feb-03 20:19 
GeneralRe: Can´t get it to work on other servers Pin
Jonatan Dahl20-Feb-03 12:50
memberJonatan Dahl20-Feb-03 12:50 
GeneralRe: Can&#180;t get it to work on other servers Pin
Slackbot2-Jun-03 12:13
memberSlackbot2-Jun-03 12:13 
GeneralRe: Can&#180;t get it to work on other servers Pin
rwilchek@att.net15-Nov-03 4:58
memberrwilchek@att.net15-Nov-03 4:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170118.1 | Last Updated 10 Oct 2002
Article Copyright 2002 by Narendra Chandel
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid