2012-11-29 37 views
0

我的PHP/MySQL Web應用程序有一個功能,可以將每個用戶的一組圖像組合成一個使用ImageMagick的PDF。每個PDF然後被放置到一個ZIP文件。每張圖片的尺寸最大可達5 MB。我的問題是瀏覽器在用戶下載文檔之前超時。如何使用PHP和ZipArchive創建ZIP文件而不發送給瀏覽器?

關於如何最好地做到這一點的任何想法?

我在想我可以在不發送給瀏覽器的情況下創建ZIP文件(即在我的代碼末尾刪除「標題」),然後通過電子郵件發送鏈接到文件;然而,它仍然要求用戶等待很長時間才能創建ZIP文件(它看起來好像瀏覽器只是懸掛着)。這可以通過AJAX在幕後完成,或者直接在服務器上完成?

$tmp_path = sys_get_temp_dir().'/'; 
$archive_name = "myarchive.zip"; 

$zip = new ZipArchive(); 

if($zip->open($archive_name,1 ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) { 
    return false; 
} 

foreach ($rows AS $row) { 

    $irows = get_images($row['user_id']); 

    $images = array(); 

    foreach($irows AS $irow){ 
     $doc = fetch_document_path($irow['id']); 
     $output_file_name = $tmp_path.$irow['id'].'.jpg'; 
     exec ('convert '.$doc.' '.$output_file_name); 
     $images[] = $irow['id'].'.jpg'; 
    }  

    $images = implode(' ', $images); 
    $output_file_name = $tmp_path.$row['name'].'.pdf'; 
    exec ('convert '.$images.' "'.$output_file_name.'"');  
    $zip->addFile($output_file_name,basename($output_file_name)); 

} 

$zip->close(); 

header('Content-type: application/zip'); 
header('Content-Disposition: attachment; filename="output.zip"'); 
readfile($archive_name); 
+0

瀏覽器正在超時或PHP?無論如何,它絕對看起來像你應該考慮創建一些將做到這一點的後臺工作。 – lupatus

回答

0

IMO你應該運行一些後臺任務,將完成這項工作。例如,後臺工作人員可以在完成後將結果文件保存到數據庫中(還可以保存更多信息,例如當前狀態和工作進度),同時網頁可以使用AJAX定期詢問服務器,如果工作已完成或最後顯示鏈接何時可用。

最簡單的方式來實現是運行腳本作爲後臺進程:

$arg1 = escapeshellarg($somearg1); 
    $arg2 = escapeshellarg($somearg1); 
    exec(sprintf('/usr/bin/php archiver.php %s %s > /dev/null 2>&1 & echo $!', $arg1, $arg2)); 

archiver.php應符合以下行開頭:

<?php 
ignore_user_abort(true); 
set_time_limit(0); 

它會防止腳本被停止時,父腳本將完成工作。

我的第二個想法是更復雜 - 你可以編寫一個守護進程,在後臺運行,等待工作。要與之通信,您可以使用隊列(如AMQP)或僅使用數據庫。使用守護進程,您可以更好地控制正在發生的事情和時間 - 在第一種方法中,您的應用程序可能會觸發太多的進程。

相關問題