4

ダウンロードのためにzipファイルをクライアントに「ストリーミング」しようとする次のビューコードがあります。

import os
import zipfile
import tempfile
from pyramid.response import FileIter

def zipper(request):
    _temp_path = request.registry.settings['_temp']
    tmpfile = tempfile.NamedTemporaryFile('w', dir=_temp_path, delete=True)

    tmpfile_path = tmpfile.name

    ## creating zipfile and adding files
    z = zipfile.ZipFile(tmpfile_path, "w")
    z.write('somefile1.txt')
    z.write('somefile2.txt')
    z.close()

    ## renaming the zipfile
    new_zip_path = _temp_path + '/somefilegroup.zip'
    os.rename(tmpfile_path, new_zip_path)

    ## re-opening the zipfile with new name
    z = zipfile.ZipFile(new_zip_path, 'r')
    response = FileIter(z.fp)

    return response

ただし、これはブラウザーで取得する応答です。

Could not convert return value of the view callable function newsite.static.zipper into a response object. The value returned was .

FileIter を正しく使用していないと思います。


アップデート:

Michael Merickel の提案で更新して以来、FileIter 関数は正しく機能しています。ただし、クライアント (ブラウザ) に表示される MIME タイプのエラーが残っています。 Resource interpreted as Document but transferred with MIME type application/zip: "http://newsite.local:6543/zipper?data=%7B%22ids%22%3A%5B6%2C7%5D%7D"

問題をよりよく説明するために、Github に小さなファイルを含めました.py: https://github.com/thapar/zipper-fix.pt

4

2 に答える 2

9

FileIterエラーメッセージが示すように、応答オブジェクトではありません。応答本文に使用できる iterable です。それだけです。また、ZipFileはファイル オブジェクトを受け入れることができます。これは、ファイル パスよりも便利です。tmpfileに書き込んでから、そのファイル ポインタを先頭に巻き戻し、それを使用して、派手な名前変更を行わずに書き出してみましょう。

import os
import zipfile
import tempfile
from pyramid.response import FileIter

def zipper(request):
    _temp_path = request.registry.settings['_temp']
    fp = tempfile.NamedTemporaryFile('w+b', dir=_temp_path, delete=True)

    ## creating zipfile and adding files
    z = zipfile.ZipFile(fp, "w")
    z.write('somefile1.txt')
    z.write('somefile2.txt')
    z.close()

    # rewind fp back to start of the file
    fp.seek(0)

    response = request.response
    response.content_type = 'application/zip'
    response.app_iter = FileIter(fp)
    return response

ドキュメントに従ってモードをオンに変更してNamedTemporaryFile、ファイルの書き込み読み取りを許可しました。'w+b'

于 2013-04-05T15:12:04.663 に答える
0

現在の Pyramid バージョンには、このユースケース用の 2 つの便利なクラス、FileResponse、FileIter があります。以下のスニペットは、静的ファイルを提供します。このコードを実行しました。ダウンロードされたファイルは、ビュー名のように「download」という名前です。ファイル名などを変更するには、Content-Disposition ヘッダーを設定するか、pyramid.response.Response の引数を調べます。

from pyramid.response import FileResponse

@view_config(name="download")
def zipper(request):    
    path = 'path_to_file'
    return FileResponse(path, request) #passing request is required

ドキュメント: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/response.html#

ヒント: 可能であればビューから Zip ロジックを抽出します

于 2013-04-05T07:40:48.187 に答える