1

ファイルストリームをディスクに保存するためにこのコードを借りましたが、ファイルのサイズが 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 がアップロードされた小さなファイルを確実に処理するにはどうすればよいでしょうか?

4

1 に答える 1

2

ファイルを開いて直接書き込むだけです。

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

注: これ (および元のソリューション) は安全ではありません。同じファイルを 2 回アップロードすると、前のファイルが上書きされ、(名前に対するサーバー フィルターによっては) ファイル名がファイル システムを横断して、tmp ディレクトリの外部にある意図しないファイルを上書きする可能性があるためです。

于 2015-08-04T16:05:53.537 に答える