2016-09-29 13 views
0

私の要件を打破しましょう。ここに私が今やっていることがあります。 WeasyprintでPDFファイルを生成し、zipファイルに保存し、そのzipファイルをクライアントに送信し、ダウンロード用に提示してください。

1.

は、以下のようなHTML私はWeasyprintを使用しています。このため

からPDFファイルを生成します。

lstFileNames = [] 
for i, content in enumerate(lstHtmlContent): 
    repName = 'report'+ str(uuid.uuid4()) + '.pdf' 
    lstFileNames.append("D:/Python/Workspace/" + repName) 

    HTML(string=content).write_pdf(target=repName, 
     stylesheets=[CSS(filename='/css/bootstrap.css')]) 

すべてのファイル名を、パスで、lstFileNamesに保存されます。

2.私は、ダウンロード

のためにクライアントにzipファイル

zipPath = 'reportDir' + str(uuid.uuid4()) + '.zip' 
myzip = zipfile.ZipFile(zipPath, 'w') 
with myzip: 
    for f in lstFileNames: 
     myzip.write(f) 

3.送信zipファイルを使用しています。このため

weasyprintによって生成されたPDFファイルとzipファイルを作成します。

resp = HttpResponse(myzip, content_type = "application/x-zip-compressed") 

resp['Content-Disposition'] = 'attachment; filename=%s' % 'myzip.zip' 

4. Javascriptでダウンロードするファイルを開きます

var file = new Blob([response], {type: 'application/x-zip-compressed'}); 
var fileURL = URL.createObjectURL(file); 
window.open(fileURL); 

問題

1. zipファイルが正常にフロントエンドで受信されている間、私はそれを開こうとした後、それが次のエラーを与える:

The archive is in either unknown format or damaged

ファイルを間違って送信していますか、またはJavascriptコードで問題が発生していますか?

2.バイト配列のリストにすべてのpdfファイルを格納し、それらのバイト配列を持つzipファイルを生成してクライアントに送信する方法はありますか?私はweasyprintでそれを試みたが、結果は同じdamaged fileだった。

3.問題はありませんが、私はweasyprint docsで見つけることができませんでした。ファイルを保存する場所へのパスを強制できますか?

問題#1は極度の優先事項であり、残りは副次的なものです。私はそれを正しくやっているかどうか、つまりpdfファイルを生成し、zipファイルをクライアントに送信しているかどうかを知りたいと思います。

ありがとうございます。

+0

サーバー上でzipファイルを開くことはできますか? –

+0

私はそれを保存したディレクトリに移動して手動で開くことができます。その中のPDFファイルも開かれています –

+0

zipファイルのURLにリダイレクトするとどうなりますか? 'window.location.href = 'リンク/ to/file.zip';'? (zipファイルを一般公開されているtmpフォルダに移動) –

答えて

0

withブロックを終了すると、ファイルハンドルが閉じられます。ファイルを開いたまま(今度は開いた状態で)再度開き、ファイルハンドル自体を渡すのではなく、内容をHttpResponseに渡すためにread()を使用する必要があります。

with zipfile.ZipFile(zipPath, 'w') as myzip 
    for f in lstFileNames: 
     myzip.write(f) 
with open(zipPath, 'r') as myzip: 
    return HttpResponse(myzip.read(), content_type = "application/x-zip-compressed") 

それが動作する場合は、zipファイルを格納する代わりに、ファイルハンドルのStringIOインスタンスを使用することができます。私はWeasyprintに慣れていないので、StringIOを使用できるかどうかわかりません。

publicPath = os.path.join('public/', os.path.basename(zipPath)) 
os.rename(zipPath, os.path.join('/var/www/', publicPath)) 

jsonResp = '{ "zip-location": "' + publicPath + '" }' 

resp = HttpResponse(jsonResp, content_type = 'application/json'); 

を次に、あなたのクライアントのJavaScriptで:

+0

で、httpresponseにそれを割り当てるとエラーになります: '' charmap 'コーデックは位置194でバイト0x90をデコードできません:文字マップは ' –

+0

になります。 rb'を開いたファイル行に挿入します。これで、 '予期しないアーカイブの終了 'というエラーを返すzipファイルが開きます。 –

+0

' myzip.read() 'を覚えましたか?私は私の元の答えでそれをすると言ったが、その例の抜粋からそれを逃した。上記の例は私のために働く。 – Alasdair

1

Aわずかに異なるアプローチ、すなわち、(例えばJSON形式)公開ディレクトリにzipファイルを移動し、クライアントにその場所を送ることであろう

var res = JSON.parse(response); 
var zipFileUrl = '/' + res['zip-location']; 

window.open(zipFileUrl, '_blank'); 

'/' + res['zip-location']あなたのページはpublicディレクトリ(ファイルシステム上の/var/www/public/pdf-files-123.zipにとてもhttp://example.com/public/pdf-files-123.zipポイント)と同じフォルダ内に住んでいることを前提としています。

publicディレクトリには、1時間以上古い.zipファイルがすべて削除されるcronジョブでクリーンアップできます。

+0

注:これはテストされていません、それはちょうどあなたにアイデアを与えることです –

+0

それは私が実際に試した最初のことです。開くファイルの場所をクライアントに送信します。 'D:/ reports/report.zip'のような絶対パスを' http://127.0.0.1:8000/report.zip'のようなサーバパスにマップする方法を理解できませんでした。パスをそのまま送信すると、URLの最後に絶対パスが追加されます。 –

+0

ローカル用であれば、[ファイルプロトコル](https://msdn.microsoft.com/en-us/library/aa767731(v=vs.85).aspx)を使用することができます。つまり、 'file:/ // D:/ reports/report.zip'。どのサーバーを使用してjavascriptをホストしていますか? –

関連する問題