#!/usr/bin/python2.4
import cherrypy
import cgi
import tempfile
import os
__author__ = "Ex Vito"
#FROM http://tools.cherrypy.org/wiki/DirectToDiskFileUpload
class myFieldStorage(cgi.FieldStorage):
"""Our version uses a named temporary file instead of the default
non-named file; keeping it visibile (named), allows us to create a
2nd link after the upload is done, thus avoiding the overhead of
making a copy to the destination filename."""
def make_file(self, binary=None):
return tempfile.NamedTemporaryFile()
def noBodyProcess():
"""Sets cherrypy.request.process_request_body = False, giving
us direct control of the file upload destination. By default
cherrypy loads it to memory, we are directing it to disk."""
cherrypy.request.process_request_body = False
cherrypy.tools.noBodyProcess = cherrypy.Tool('before_request_body', noBodyProcess)
class fileUpload:
"""fileUpload cherrypy application"""
@cherrypy.expose
def index(self):
"""Simplest possible HTML file upload form. Note that the encoding
type must be multipart/form-data."""
return """
<html>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
File: <input type="file" name="theFile"/> <br/>
<input type="submit"/>
</form>
</body>
</html>
"""
@cherrypy.expose
@cherrypy.tools.noBodyProcess()
def upload(self, theFile=None):
"""upload action
We use our variation of cgi.FieldStorage to parse the MIME
encoded HTML form data containing the file."""
# the file transfer can take a long time; by default cherrypy
# limits responses to 300s; we increase it to 1h
cherrypy.response.timeout = 3600
# convert the header keys to lower case
lcHDRS = {}
for key, val in cherrypy.request.headers.iteritems():
lcHDRS[key.lower()] = val
# at this point we could limit the upload on content-length...
# incomingBytes = int(lcHDRS['content-length'])
# create our version of cgi.FieldStorage to parse the MIME encoded
# form data where the file is contained
formFields = myFieldStorage(fp=cherrypy.request.rfile,
headers=lcHDRS,
environ={'REQUEST_METHOD':'POST'},
keep_blank_values=True)
# we now create a 2nd link to the file, using the submitted
# filename; if we renamed, there would be a failure because
# the NamedTemporaryFile, used by our version of cgi.FieldStorage,
# explicitly deletes the original filename
theFile = formFields['theFile']
os.link(theFile.file.name, '/tmp/'+theFile.filename)
return "ok, got it filename='%s'" % theFile.filename
# remove any limit on the request body size; cherrypy's default is 100MB
# (maybe we should just increase it ?)
cherrypy.server.max_request_body_size = 0
# increase server socket timeout to 60s; we are more tolerant of bad
# quality client-server connections (cherrypy's defult is 10s)
cherrypy.server.socket_timeout = 60
tutconf = os.path.join(os.path.dirname(__file__), 'cherrypy_file.conf')
if __name__ == '__main__':
# CherryPy always starts with app.root when trying to map request URIs
# to objects, so we need to mount a request handler root. A request
# to '/' will be mapped to HelloWorld().index().
cherrypy.quickstart(fileUpload(), config=tutconf)
else:
# This branch is for the test suite; you can ignore it.
cherrypy.tree.mount(fileUpload(), config=tutconf)
#cherrypy.quickstart(fileUpload())