16

私はそれを送信するために一時ファイルを作成する必要があります、私は試しました:

# Create a temporary file --> I think it is ok (file not seen)
temporaryfile = NamedTemporaryFile(delete=False, dir=COMPRESSED_ROOT)

# The path to archive --> It's ok
root_dir = "something"

# Create a compressed file --> It bugs
data = open(f.write(make_archive(f.name, 'zip', root_dir))).read()

# Send the file --> Its ok
response = HttpResponse(data, mimetype='application/zip')
response['Content-Disposition'] = 'attachment; filename="%s"' % unicode(downloadedassignment.name + '.zip')
return response

それが良いアプローチかどうかはまったくわかりません。

4

2 に答える 2

31

私は実際に同じようなことをする必要があり、可能であればファイルI/Oを完全に避けたかったのです。これが私が思いついたものです:

import tempfile
import zipfile

with tempfile.SpooledTemporaryFile() as tmp:
    with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as archive:
        archive.writestr('something.txt', 'Some Content Here')

    # Reset file pointer
    tmp.seek(0)

    # Write file data to response
    return HttpResponse(tmp.read(), mimetype='application/x-zip-compressed')

を使用するSpooledTemporaryFileため、メモリ制限を超えない限り、メモリ内に残ります。次に、この一時ファイルを使用するストリームとして設定ZipFileします。渡されるwritestrファイル名は、ファイルがアーカイブ内に持つファイル名であり、サーバーのファイルシステムとは何の関係もありません。次に、ファイルポインター( )を実行しseek(0)た後、ファイルポインター()を巻き戻しZipFileて、応答にダンプする必要があります。

于 2012-08-15T14:48:26.697 に答える
11

まず、NamedTemporaryFile使用するためにを作成する必要はありませんmake_archive。必要なのは、make_archive作成するファイルの一意のファイル名だけです。

.writeファイル名を返さない

そのエラーに焦点を当てるには:の戻り値はf.write開くことができるファイル名であると想定しています。ファイルの先頭を探して、代わりに読んでください。

f.write(make_archive(f.name, 'zip', root_dir))
f.seek(0)
data = f.read()

作成した(設定した)一時ファイルクリーンアップする必要があることに注意してください。delete=False

import os
f.close()
os.unlink(f.name)

deleteまたは、キーワードを省略してデフォルトにTrue戻し、後でファイルを閉じるだけにします。リンクを解除する必要はありません。

アーカイブファイル名を新しいファイルに書き込んだだけです。

新しいアーカイブ名を一時ファイルに書き込んでいるだけです。アーカイブを直接読む方がよいでしょう。

data = open(make_archive(f.name, 'zip', root_dir), 'rb').read()

現在、一時ファイルはまったく書き込まれていないことに注意してください。

これを行うための最良の方法

NamedTemporaryFile完全に作成することは避けてください。tempfile.mkdtemp()代わりに、アーカイブを配置する一時ディレクトリを生成し、後でそれをクリーンアップするために使用します。

tmpdir = tempfile.mkdtemp()
try:
    tmparchive = os.path.join(tmpdir, 'archive')

    root_dir = "something"

    data = open(make_archive(tmparchive, 'zip', root_dir), 'rb').read()

finally:
    shutil.rmtree(tmpdir)
于 2012-08-15T10:29:25.373 に答える