2014-03-03 39 views
1

在當前的PHP項目中,我需要在一些歸檔中捆綁一堆PDF文件,以便用戶可以一起下載它們。由於zip是最常見的,即使是最基本的非IT-Windows的人都知道,我正在尋找一個zip存檔。在PHP中創建大型壓縮文檔

我的代碼如下所示

$invoices = getRequestedInvoices(); // load all requested invoices, this function is just for demonstration 

// Create a temporary zip archive 
$filename = tempnam("tmp", "zip"); 
$zip = new \ZipArchive(); 
$zip->open($filename, \ZipArchive::OVERWRITE); 

foreach($invoices as $invoice) 
{ 
    // create the pdf file and add it to the archive 
    $pdf = new InvoicePdf($invoice); // this is derived from \ZendPdf\PdfDocument 
    $zip->addFromString($pdf->getFilename(), $pdf->render()); // for clarification: the getFilename method creates a filename for the PDF based on the invoice's id 
} 

$zip->close(); 

header('Content-Type: application/zip'); 
header('Content-Length: ' . filesize($filename)); 
header('Content-Disposition: attachment; filename="invoices.zip"'); 
readfile($filename); 
unlink($filename); 
exit; 

如果服務器有足夠的內存該腳本能正常工作。不幸的是,我們的生產系統非常有限,所以該腳本僅適用於一些PDF文件,但大多數情況下它會耗盡內存並中止。在foreach循環結尾添加unlink($ pdf)沒有幫助,所以我的猜測是ZipArchive對象正在使用內存。

我想添加儘可能少的依賴項目,所以我很樂意能夠解決這個PHP(PHP 5.4)自己的函數或Zend Framework 2函數。我正在尋找一些方法直接對檔案進行流式傳輸(zip://流包裝首先看起來不錯,但它是隻讀的),但對於zip檔案來說這似乎是不可能的。

有沒有人有想法?也許是一種不同但也廣爲人知的允許流式傳輸的存檔類型?壓縮不是必須的

+2

如果你受內存限制,那麼不要使用內置的zip文件。你可以執行'exec(「zip $ filename file1 file2 file3」)',而不會受PHP的內存限制。您必須非常小心各種文件名以防止shell注入攻擊,但它會爲您提供zip文件而不會導致PHP出現內存不足錯誤。 –

+0

我想過,但這種方式平臺獨立?當我們可能遷移到不同的服務器(具有未知屬性)時,我需要牢記未來。 – Subsurf

+0

不是真的。一旦你開始處理shell,你基本上依賴於平臺。 –

回答

0

我不得不尋找這個問題的快速解決方案,所以儘管試圖避免它,我不得不使用外部依賴。

我從PHPZip項目(https://github.com/Grandt/PHPZip)中找到了ZipStream類,它很好地完成了這項工作。

$zip = new \ZipStream("invoices.zip"); 

foreach($invoices as $invoice) 
{ 
    $pdf = new InvoicePdf($invoice); 
    $zip->addFile($pdf->render(), $pdf->getFilename()); 
} 

$zip->finalize(); 
exit;