I borrowed this code for saving a file stream to disk, and it works except for when the file is less than 1kb in size. I get this error:
in stuff_uploaded:
copy(theFile.file.name, './tmp/'+theFile.filename) #saves temporary file to /cp2/tmp/
AttributeError: 'cStringIO.StringO' object has no attribute 'name'
@cherrypy.expose
@cherrypy.tools.noBodyProcess()
def stuff_uploaded(self, theFile=None):
import cgi
import tempfile
# convert the header keys to lower case
lcHDRS = {key.lower():val for key, val in cherrypy.request.headers.iteritems()}
class myFieldStorage(cgi.FieldStorage):
"""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()
formFields = myFieldStorage(fp=cherrypy.request.rfile,
headers=lcHDRS,
environ={'REQUEST_METHOD':'POST'},
keep_blank_values=True)
theFile = formFields['theFile']
# we now create a 2nd link to the file, using the submitted filename.
from shutil import copy
copy(theFile.file.name, './tmp/'+theFile.filename) #saves temporary file
msgs = csv_to_survey.match_fieldnames('./tmp/'+theFile.filename)
return './tmp/'+theFile.filename
So what can I do to ensure that cStringIO.StringO handles small uploaded files?
Just open and write the file directly:
Or to deal with it regardless of whether the file is on disk or
StringIO, use it as a file-like object:Note: This (and your original solution) is insecure, since uploading the same file twice will overwrite the previous file, and (depending on server filters on names) file names could traverse the file system to overwrite unintended files outside the tmp directory.