2012-11-29 33 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)或仅使用数据库。使用守护进程,您可以更好地控制正在发生的事情和时间 - 在第一种方法中,您的应用程序可能会触发太多的进程。

相关问题