2012-01-05 8 views
2

私はdjangoでのファイルダウンロードを管理するための次のコードを用意しています。djangoが提供する空のファイルを取得する

def serve_file(request, id): 

    file = models.X.objects.get(id=id).file #FileField 
    file.open('rb') 
    wrapper = FileWrapper(file) 
    mt = mimetypes.guess_type(file.name)[0] 
    response = HttpResponse(wrapper, content_type=mt) 

    import unicodedata, os.path 
    filename = unicodedata.normalize('NFKD', os.path.basename(file.name)).encode("utf8",'ignore') 
    filename = filename.replace(' ', '-') #Avoid browser to ignore any char after the space 

    response['Content-Length'] = file.size 
    response['Content-Disposition'] = 'attachment; filename={0}'.format(filename) 

    #print response 
    return response 

残念ながら、私のブラウザはダウンロード時に空のファイルを取得します。

印刷された応答が正しいようだ:

Content-Length: 3906 
Content-Type: text/plain 
Content-Disposition: attachment; filename=toto.txt 

blah blah .... 

私は似たコードOK実行されています。何が問題なのか分かりません。何か案が?

PS:私は解決策がhereを提案し、同じ動作を取得テストしている

アップデート:私はprint responseコメントした場合、私は同様の問題を得る: はwrapper = file.read()によってwrapper = FileWrapper(file)が問題に

更新を解決するよう交換:。ファイルは空です。差異のみ:FFは20バイトのサイズを検出します。 (ファイルがこれより大きい)

答えて

1

ファイルオブジェクトは、互換性があり、ジェネレータです。それはexaustedされる前に一度だけ読み取ることができます。次に、新しいものを作成する必要があります。オブジェクトの最初から開始するメソッドを使用します(例:seek())。

read()は何も問題なく何度も読むことができる文字列を返します。これがあなたの問題を解決する理由です。

したがって、オブジェクトのようなファイルを使用する場合は、行内に2回読み込まないようにしてください。 E.G:それを印刷せずに返します。 django documentationから

+0

良い点!しかし、私は印刷物にコメントしても、同様の動作をしています(実際には、鉛筆を理解しようとするために印刷物を追加しました)。私の更新を参照してください – luc

+0

ええ、しかし、応答は一度だけ繰り返されていることは何を示唆していますか?結局のところ、レスポンスはあなたのファイルラッパーをafterallの内容に使用します。 –

0

FieldFile.open(モード= 'RB')は、標準のPythonオープン() メソッドのように動作し、モードによって指定されたモード このインスタンスに関連付けられたファイルを開きます。

それはニシキヘビopenのように動作している場合、それはファイルオブジェクトを返す必要があり、このように使用する必要があります。

f = file.open('rb') 
wrapper = FileWrapper(f) 
+0

file.openは何も返さずファイルインスタンスを変更するようです – luc

関連する問題