strip the local directory with os.path.split to get the remote name, or accept two
distinct filename arguments—local and remote.)
Also notice that, despite its name, this module is very different from the getfile.py script
we studied at the end of the sockets material in the preceding chapter. The socket-based
getfile implemented custom client and server-side logic to download a server file to a
client machine over raw sockets.
The new getfile here is a client-side tool only. Instead of raw sockets, it uses the
standard FTP protocol to request a file from a server; all socket-level details are hidden
in the simpler ftplib module’s implementation of the FTP client protocol. Further-
more, the server here is a perpetually running program on the server machine, which
listens for and responds to FTP requests on a socket, on the dedicated FTP port (number
21). The net functional effect is that this script requires an FTP server to be running on
the machine where the desired file lives, but such a server is much more likely to be
available.
Upload utility
While we’re at it, let’s write a script to upload a single file by FTP to a remote machine.
The upload interfaces in the FTP module are symmetric with the download interfaces.
Given a connected FTP object, its:
- storbinary method can be used to upload bytes from an open local file object
- storlines method can be used to upload text in ASCII mode from an open local
file object
Unlike the download interfaces, both of these methods are passed a file object as a
whole, not a file object method (or other function). We will meet the storlines method
in a later example. The utility module in Example 13-5 uses storbinary such that the
file whose name is passed in is always uploaded verbatim—in binary mode, without
Unicode encodings or line-feed translations for the target machine’s conventions. If
this script uploads a text file, it will arrive exactly as stored on the machine it came
from, with client line-feed markers and existing Unicode encoding.
Example 13-5. PP4E\Internet\Ftp\putfile.py
#!/usr/local/bin/python
"""
Store an arbitrary file by FTP in binary mode. Uses anonymous
ftp unless you pass in a user=(name, pswd) tuple of arguments.
"""
import ftplib # socket-based FTP tools
def putfile(file, site, dir, user=(), *, verbose=True):
"""
store a file by ftp to a site/directory
anonymous or real login, binary transfer
864 | Chapter 13: Client-Side Scripting