This is a bare-bones cgi file upload. It will display an upload form and save the uploaded files to disk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #!/usr/local/bin/python
"""This demonstrates a minimal http upload cgi.
This allows a user to upload up to three files at once.
It is trivial to change the number of files uploaded.
This script has security risks. A user could attempt to fill
a disk partition with endless uploads.
If you have a system open to the public you would obviously want
to limit the size and number of files written to the disk.
"""
import cgi
import cgitb; cgitb.enable()
import os, sys
try: # Windows needs stdio set for binary mode.
import msvcrt
msvcrt.setmode (0, os.O_BINARY) # stdin = 0
msvcrt.setmode (1, os.O_BINARY) # stdout = 1
except ImportError:
pass
UPLOAD_DIR = "/tmp"
HTML_TEMPLATE = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><title>File Upload</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head><body><h1>File Upload</h1>
<form action="%(SCRIPT_NAME)s" method="POST" enctype="multipart/form-data">
File name: <input name="file_1" type="file"><br>
File name: <input name="file_2" type="file"><br>
File name: <input name="file_3" type="file"><br>
<input name="submit" type="submit">
</form>
</body>
</html>"""
def print_html_form ():
"""This prints out the html form. Note that the action is set to
the name of the script which makes this is a self-posting form.
In other words, this cgi both displays a form and processes it.
"""
print "content-type: text/html\n"
print HTML_TEMPLATE % {'SCRIPT_NAME':os.environ['SCRIPT_NAME']}
def save_uploaded_file (form_field, upload_dir):
"""This saves a file uploaded by an HTML form.
The form_field is the name of the file input field from the form.
For example, the following form_field would be "file_1":
<input name="file_1" type="file">
The upload_dir is the directory where the file will be written.
If no file was uploaded or if the field does not exist then
this does nothing.
"""
form = cgi.FieldStorage()
if not form.has_key(form_field): return
fileitem = form[form_field]
if not fileitem.file: return
fout = file (os.path.join(upload_dir, fileitem.filename), 'wb')
while 1:
chunk = fileitem.file.read(100000)
if not chunk: break
fout.write (chunk)
fout.close()
save_uploaded_file ("file_1", UPLOAD_DIR)
save_uploaded_file ("file_2", UPLOAD_DIR)
save_uploaded_file ("file_3", UPLOAD_DIR)
print_html_form ()
|
This demonstrates a minimal http upload cgi. This is a self-posting cgi, so it will both display an upload form as well as process any uploaded files. Uploaded files are saved to the UPLOAD_DIR which is currently set to "/tmp".
This script has security risks. A user could attempt to fill a disk partition with endless uploads. If you have a system open to the public you would obviously want to limit the size and number of files written to the disk.
It seems that on Windows, you have to switch to binary mode to be able to upload binary files like pictures
Sample. ... and just to share my version: http://zxw.nm.ru/test_w_upload.py.htm
Editor Note (June 2010): The above link no longer exists, it redirects to an inappropriate and unrelated site. The link has been updated to the Internet Archive version. See all archived versions of this URL.
documentation for upload.cgi ? drats!
this script (as well as the one by Georgy Pruss that's mentioned in the thread) looks easy enough to implement but i'm having no luck.
is there more documentation i can refer to for setting this up? thanks
file upload problem.
cgi.FieldStorage instantiation. I guess that's because they way the original script is written, FieldStorage gets instantiated three times, each time the save_upload() function is called. But probably already at the first time the FiledStorgae eats up alls data from sys.stdin where the uploaded files are provided.
So FieldStorage should be instantiated only once and then either made available, as you suggested, as a global variable or handed over as a third argument to the save_upload() function.
File Transfer. How does the CGI module get a file from a client's computer? Also, how does the CGI module get data from the POST method? I have written a lightweight version of the CGI module, but getting files is something that it cannot do yet. The CGI programs that currently work with it do not specify a method.
Example needs work. I think that what is missing in this script is the author's SCRIPT_NAME environment variable. This example will not work otherwise.
Ive tried to set this to the script name itself sys.argv[0] with no luck.. So what is this supposed to be set to ?
answered. I got an answer to my own question. The problem I had was that I was using a SimpleHTTPServer python script. This dosn't set a SCRIPT_NAME env variable which Apache sets.
Apache would have set to something like /cgi-bin/upload.cgi if this sctipt was called upload.cgi (presuming that you made your cgi directory cgi_bin
Test drive at my linux server. I corrected it as follows to work well....
form=cgi.FieldStorage() # put this before HTML_TEMPLATE definition
... at print_html_form() funtion;
There's no os.environ['SCRIPT_NAME'] --> os.environ
['SCRIPT_FILENAME'], and considering your url...
a='your_web_url_to_cgi/'+os.environ['SCRIPT_FILENAME'].split('/')[-1]
print HTML_TEMPLATE % {'SCRIPT_NAME':a}
... at save_uploaded_file() funtion;
global form
Now it works well...