PythonUpload

From XPUB & Lens-Based wiki

Enabling File Upload in a Python CGI

Simple HTML form to upload a file, note that the action needs to set to the proper URL of the upload.cgi script (which follows below).

upload.html

<html>
<head>
<title>file upload</title>
</head>
<body>
<form action="/cgi-bin/upload.cgi" method="post" enctype="multipart/form-data">
<p>Ready to upload a file.</p>
<p><input type="file" name="attachment" /></p>
<p><input type="submit" value="upload now" /></p>
</form>
</body>
</html>

Script to receive and save a file from a multipart (file upload) form.

upload.cgi

#!/usr/bin/python

import cgi
import cgitb; cgitb.enable()

"""
	upload.cgi
	
	receives an uploaded file with the name attachment
	this code could be generalized!

"""

# cgi.test()

def writeFileToPath(file, outputPath):
	"""
	requires: file object (not processed if false), outputPath is the full path and filename to be opened for writing
	effects: saves the contents of the file object to outputPath
	returns: number of bytes written to the outputPath
	"""
	bytesWritten = 0
	if file:
		out = 0
		while 1:
			bytes = file.read(1024)
			if not bytes: break
			if not out:
				out = open(outputPath, 'w')
			out.write(bytes)
			bytesWritten += len(bytes)
		if out:
			out.close

	return bytesWritten

form = cgi.FieldStorage()
attachment = form['attachment']
print "Content-type: text/html"
print

def getUploadFilename(attachment):
	"""
	Returns the filename (excluding any path) from the attachment
	On IE/Windows, attachment.filename will be the CLIENT'S FULL LOCAL PATH to the uploaded file, not just the filename
	e.g. 'C:\Desktop\BlahBlah\foo.jpg'
	so this just takes whatever's to the right of the right-most backslash
	e.g. 'foo.jpg'
	"""
	filename = attachment.filename
	backslash_pos = filename.rfind('\\')
	if (backslash_pos >= 0):
		filename = filename[backslash_pos+1:]
	return filename

bytesWritten = writeFileToPath(attachment.file, "attachments/" + getUploadFilename(attachment))
if bytesWritten:
	print "<p>Uploaded %d bytes to %s.</p>" % (bytesWritten, attachment.filename)
else:
	print "<p>No file to upload.</p>"