Foundations of Python Network Programming

(WallPaper) #1

Chapter 17 ■ Ftp


322


Listing 17-4. Binary Download with Status Updates


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter17/advbinarydl.py


import os, sys
from ftplib import FTP


def main():
if os.path.exists('linux-1.0.tar.gz'):
raise IOError('refusing to overwrite your linux-1.0.tar.gz file')


ftp = FTP('ftp.kernel.org')
ftp.login()
ftp.cwd('/pub/linux/kernel/v1.0')
ftp.voidcmd("TYPE I")


socket, size = ftp.ntransfercmd("RETR linux-1.0.tar.gz")
nbytes = 0


f = open('linux-1.0.tar.gz', 'wb')


while True:
data = socket.recv(2048)
if not data:
break
f.write(data)
nbytes += len(data)
print("\rReceived", nbytes, end=' ')
if size:
print("of %d total bytes (%.1f%%)"
% (size, 100 * nbytes / float(size)), end=' ')
else:
print("bytes", end=' ')
sys.stdout.flush()


print()
f.close()
socket.close()
ftp.voidresp()
ftp.quit()


if name == 'main':
main()


There are a few new things to note here. First is the call to voidcmd(). This passes an FTP command directly
to the server and checks for an error, but returns nothing. In this case, the raw command is TYPE I. This sets the
transfer mode to “image,” which is how FTP refers internally to binary files. In the previous example, retrbinary()
automatically ran this command behind the scenes, but the lower-level ntransfercmd() does not.

Free download pdf