2016-09-29 28 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.創建與weasyprint

這個生成的PDF文件的zip文件,我使用的壓縮文件

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

3.發送壓縮文件給客戶端下載

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); 

問題

雖然在前端被成功接收的zip文件,之後我嘗試打開它,它提供了以下錯誤:

The archive is in either unknown format or damaged

我發送的文件是錯誤的還是我的Javascript代碼有問題?

2.有沒有辦法將所有pdf文件存儲在字節數組列表中,並用這些字節數組生成zip文件並將其發送到客戶端?我用weasyprint試過,但結果是相同的damaged file

3.不完全是一個問題,但我一直沒能在weasyprint文檔中找到它。我可以強制執行文件保存位置的路徑嗎?

問題1是極其重要的,其餘的都是次要的。我想知道我是否正確地做,即生成pdf文件並將其zip文件發送到客戶端。

在此先感謝。

+0

你能打開服務器上的zip文件嗎? –

+0

我可以通過轉到保存的目錄手動打開它。其中的PDF文件也正在打開 –

+0

如果您只是重定向到zip文件的url,會發生什麼情況。 'window.location.href ='link/to/file.zip';'? (將zip文件移動到公共可用的tmp文件夾中) –

回答

0

退出with塊後,文件句柄關閉。您應該重新打開文件(這次打開)並使用read()將內容傳遞到HttpResponse而不是傳遞文件句柄本身。

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") 

如果這樣的作品,那麼你可以使用一個StringIO實例,而不是一個文件句柄來存儲壓縮文件。我不熟悉Weasyprint,所以我不知道你是否可以使用StringIO

+0

打開文件並將其分配給httpresponse給出錯誤:''charmap'編解碼器無法解碼位置194中的字節0x90:字符映射到' –

+0

我修正了通過添加' rb'在打開的文件行中。現在它打開提供'意外結束存檔'錯誤的zip文件 –

+0

您是否記得使用'myzip.read()'?我說在我的原始答案中這樣做,但錯過了示例代碼片段。上面的例子適用於我。 – Alasdair

1

一個稍微不同的方法將zip文件移動到一個公共目錄中,然後發送該位置給客戶端(例如JSON格式),即:

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:

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

window.open(zipFileUrl, '_blank'); 

'/' + res['zip-location']假定您的網頁住在同一文件夾中public目錄(所以http://example.com/public/pdf-files-123.zip/var/www/public/pdf-files-123.zip您的文件系統)。

您可以使用cron作業來清理public目錄,該作業會刪除那些大於一個小時左右的所有.zip文件。

+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:/報告/ report.zip'。你用什麼服務器來託管JavaScript? –