1

django httpの応答でzipファイルを返そうとしていますが、コードは次のようになります...

archive = shutil.make_archive('testfolder', 'zip', MEDIA_ROOT, 'testfolder')
response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])
response['Content-Length'] = getsize(archive)
response['Content-Disposition'] = "attachment; filename=test %s.zip" % datetime.now()
return response

このコードをubuntuで実行すると、ダウンロードされたファイルは問題なく開きますが、Windowsで実行すると、作成されたファイルはwinzipで開きません(エラー「サポートされていないZip形式」が表示されます)。

私がここで見逃している非常に明白な何かがありますか?Pythonコードは移植可能であると想定されていませんか?

編集:

コメントをくれたJFセバスティアンに感謝します...

アーカイブの作成に問題はなく、リクエストに読み戻されていました。したがって、解決策は、コードの2行目を次のように変更することです。

response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])

に、

response = HttpResponse(FileWrapper(open(archive, 'rb')),  # notice extra 'rb'
                           content_type=mimetypes.guess_type(archive)[0])

チェックアウト、詳細についてはこの質問への私の答え...

4

2 に答える 2

1

作成したコードは正しく機能するはずです。スニペットから次の行を実行してzipファイルを生成し、LinuxとWindowsで抽出できました。

archive = shutil.make_archive('testfolder', 'zip', MEDIA_ROOT, 'testfolder')

何かおかしくて具体的なことが起こっています。以下を確認することをお勧めします。

  1. その1つのライナーだけを持つスクリプトを使用して、Djangoの外部でzipファイルを生成します。次に、Windowsマシンでそれを抽出してみてください。これは、Django、Webサーバー、またはブラウザーに関連して発生していることをすべて除外するのに役立ちます
  2. それが機能する場合は、圧縮したフォルダーの内容を正確に確認してください。ファイルの名前に面白い文字が含まれていますか、奇妙なファイルタイプ、または非常に長いファイル名がありますか?
  3. WindowsとLinuxのzipファイルでmd5チェックサムを実行して、2つのファイルがバイトごとに同一であることを完全に確認します。発生した可能性のあるファイルの破損を除外するため。
于 2012-10-02T20:38:17.613 に答える
1

JF Sebastianのコメントに感謝します...

私はまだここに解決策を詳細に書きます...

アーカイブの作成に問題はなく、リクエストに読み込んでいました。したがって、解決策は、コードの 2 行目を次のように変更することです。

response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])

に、

response = HttpResponse(FileWrapper(open(archive, 'rb')),  # notice extra 'rb'
                           content_type=mimetypes.guess_type(archive)[0])

どうやら、上のpython 2.3ドキュメントのどこかに隠されているためですopen

mode の最も一般的に使用される値は、読み取り用の 'r'、書き込み用の 'w' (ファイルが既に存在する場合はファイルを切り捨てる)、および追加用の 'a' (一部の Unix システムでは、すべての書き込みが最後に追加されることを意味します) です。現在のシーク位置に関係なく、ファイルの モードが省略された場合、デフォルトは 'r' になります。デフォルトではテキスト モードが使用されます。このモードでは、'\n' 文字が書き込み時にプラットフォーム固有の表現に変換され、読み取り時に元に戻されます。したがって、バイナリ ファイルを開くときは、モード値に「b」を追加してファイルをバイナリ モードで開く必要があります 。これにより、移植性が向上します(追加の 'b' は、バイナリ ファイルとテキスト ファイルを異なる方法で処理しないシステムでも、ドキュメントとして機能する場合に役立ちます。

つまり、簡単に言えば、バイナリ ファイルの読み取り中に使用open(file, 'rb')すると、コードの移植性が向上します (この場合は確かにそうでした)。

これで、Windows で問題なく抽出できます...

于 2012-10-23T22:28:02.057 に答える