faqts : Computers : Programming : Languages : Python : Snippets : Network Tools

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

3 of 4 people (75%) answered Yes
Recently 2 of 3 people (67%) answered Yes

Entry

Resuming with ftplib/httplib?

Jul 5th, 2000 10:00
Nathan Wallace, unknown unknown, Hans Nowak, Snippet 170, Henning Schroeder


"""
Packages: networking.internet
"""
"""
> So my question is, how can I, using ftplib and httplib, resume a
> download? Is it possible? Has this been done before? Any code someone
> would be willing to share? I would appreciate it soo much. :-)
HTTP version 1.1 supports byte ranges. There is an interesting article
in
ApacheWeek (http://www.apacheweek.org) about HTTP 1.1.
The ftp-protocoll has a REST command to resume transfers. See the hack 
below which works for me.
  Henning
"""
#------------------------------------------------------------
# Module xftplib.py
from ftplib import *
class XFTP(FTP):
    def size(self, filename):
	self.voidcmd("TYPE I") #seems necessary to get the *right* size	
	return FTP.size(self, filename)
    def rest(self, start):
	resp = self.sendcmd("REST %s" % start)
	if resp[:3] <> "350": raise error_reply, resp
    def ntransfercmd(self, cmd, resume):
	'''Initiate a transfer over the data connection.
	If the transfer is active, send a port command and
	the transfer command, and accept the connection.
	If the server is passive, send a pasv command, connect
	to it, and start the transfer command.
	Either way, return the socket for the connection and
	the expected size of the transfer.  The expected size
	may be None if it could not be determined.'''
	size = None
	if self.passiveserver:
	    host, port = parse227(self.sendcmd('PASV'))
	    conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	    conn.connect(host, port)
	    if resume: self.rest(resume)
	    resp = self.sendcmd(cmd)
	    if resp[0] <> '1':raise error_reply, resp
	else:
	    sock = self.makeport()
	    if resume: self.rest(resume)
	    resp = self.sendcmd(cmd)
	    if resp[0] <> '1':
		raise error_reply, resp
	    conn, sockaddr = sock.accept()
	    if resp[:3] == '150':
		# this is conditional in case we received a 125
		size = parse150(resp)
	    return conn, size
    def transfercmd(self, cmd, resume=0):
	'''Initiate a transfer over the data connection.  Returns
	the socket for the connection.  See also ntransfercmd().'''
	return self.ntransfercmd(cmd, resume)[0]
    def retrbinary(self, cmd, callback, resume=0, blocksize=8192):
	    '''Retrieve data in binary mode.
	    The argument is a RETR command.
	    The callback function is called for each block.
	    This creates a new port for you'''
	    self.voidcmd('TYPE I')
	    conn = self.transfercmd(cmd, resume)
	    while 1:
		    data = conn.recv(blocksize)
		    if not data:
			    break
		    callback(data)
	    conn.close()
	    return self.voidresp()