cStringIO.StringO 当文件小于 1kByte 时,无法保存上传的文件流
cStringIO.StringO fails to save uploaded file stream when file is smaller than 1kByte
我借用了这段代码来将文件流保存到磁盘,除了文件小于 1kb 的情况外,它都能正常工作。我收到此错误:
in stuff_uploaded:
copy(theFile.file.name, './tmp/'+theFile.filename) #saves temporary file to /cp2/tmp/
AttributeError: 'cStringIO.StringO' 对象没有属性 '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
那么我该怎么做才能确保 cStringIO.StringO 处理上传的小文件?
直接打开并写入文件即可:
with open('./tmp/'+theFile.filename, "w") as f:
f.write(theFile.file.getvalue())
或者不管文件是在磁盘上还是在StringIO
上都处理它,把它当作类文件对象来处理:
import shutil
with open('./tmp/'+theFile.filename, "w") as f:
# If the file pointer might not be at the beginning of theFile.file, add:
# theFile.file.seek(0)
shutil.copyfileobj(theFile.file, f)
# While:
# f.write(theFile.file.read())
# would work most of the time, it involves holding the whole contents of the
# file in memory at once (which you want to avoid; that's why CherryPy
# uses temp files for larger data). shutil.copyfileobj does block by
# block copies, which have fixed peak memory usage while still running
# (almost) as fast
注意:这个(和你原来的解决方案)是不安全的,因为上传同一个文件两次会覆盖以前的文件,并且(取决于名称的服务器过滤器)文件名可以遍历文件系统以覆盖外部不需要的文件tmp 目录。
我借用了这段代码来将文件流保存到磁盘,除了文件小于 1kb 的情况外,它都能正常工作。我收到此错误:
in stuff_uploaded:
copy(theFile.file.name, './tmp/'+theFile.filename) #saves temporary file to /cp2/tmp/
AttributeError: 'cStringIO.StringO' 对象没有属性 '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
那么我该怎么做才能确保 cStringIO.StringO 处理上传的小文件?
直接打开并写入文件即可:
with open('./tmp/'+theFile.filename, "w") as f:
f.write(theFile.file.getvalue())
或者不管文件是在磁盘上还是在StringIO
上都处理它,把它当作类文件对象来处理:
import shutil
with open('./tmp/'+theFile.filename, "w") as f:
# If the file pointer might not be at the beginning of theFile.file, add:
# theFile.file.seek(0)
shutil.copyfileobj(theFile.file, f)
# While:
# f.write(theFile.file.read())
# would work most of the time, it involves holding the whole contents of the
# file in memory at once (which you want to avoid; that's why CherryPy
# uses temp files for larger data). shutil.copyfileobj does block by
# block copies, which have fixed peak memory usage while still running
# (almost) as fast
注意:这个(和你原来的解决方案)是不安全的,因为上传同一个文件两次会覆盖以前的文件,并且(取决于名称的服务器过滤器)文件名可以遍历文件系统以覆盖外部不需要的文件tmp 目录。