need to be specific since the path comes from another machine. Note that we could
have instead coded the path splitter logic like this to avoid some split calls:
def splitpath(origpath): # get name at end
basename = os.path.split(origpath)[1] # try server paths
if basename == origpath: # didn't change it?
if '\\' in origpath:
basename = origpath.split('\\')[-1] # try DOS clients
elif '/' in origpath:
basename = origpath.split('/')[-1] # try Unix clients
return basename
But this alternative version may fail for some path formats (e.g., DOS paths with a drive
but no backslashes). As is, both options waste time if the filename is already a base
name (i.e., has no directory paths on the left), but we need to allow for the more complex
cases generically.
This upload script works as planned, but a few caveats are worth pointing out before
we close the book on this example:
- Firstly, putfile doesn’t do anything about cross-platform incompatibilities in
filenames themselves. For instance, spaces in a filename shipped from a DOS client
are not translated to nonspace characters; they will wind up as spaces in the server-
side file’s name, which may be legal but are difficult to process in some scenarios. - Secondly, reading line by line means that this CGI script is biased toward uploading
text files, not binary datafiles. It uses a wb output open mode to retain the binary
content of the uploaded file, but it assumes the data is text in other places, including
the reply page. See Chapter 4 for more about binary file modes. This is all largely
a moot point in Python 3.1, though, as binary file uploads do not work at all (see
“CGI File Upload Limitations in 3.1”); in future release, though, this would need
to be addressed.
If you run into any of these limitations, you will have crossed over into the domain of
suggested exercises.
CGI File Upload Limitations in 3.1
Regrettably, I need to document the fact that Python’s standard library support for CGI
file uploads is partially broken in Python 3.1, the version used for this edition. In short,
the cgi module’s internal parsing step fails today with an exception if any binary file
data or incompatible text file data is uploaded. This exception occurs before the script
has a chance to intervene, making simple workarounds nonviable. CGI uploads worked
in Python 2.X because strings handled bytes, but fail in 3.X today.
This regression stems in part from the fact that the cgi module uses the email package’s
parser to extract incoming multipart data for files, and is thus crippled by some of the
very same email package issues we explored in detail in Chapter 13—its email parser
requires str for the full text of a message to be parsed, but this is invalid for some CGI
upload data. As mentioned in Chapter 13, the data transmitted for CGI file uploads
might have mixed text and binary data—including raw binary data that is not
Transferring Files to Clients and Servers | 1225