0

我的 PHP/MySQL Web 应用程序具有使用 ImageMagick 将每个用户的一组图像组合成单个 PDF 的功能。然后将每个 PDF 放入一个 ZIP 文件中。每个图像的大小最大为 5 MB。我的问题是浏览器在用户下载文档之前超时。

关于如何最好地做到这一点的任何想法?

我在想我可以创建 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);
4

1 回答 1

0

IMO 你应该运行一些后台任务来完成这项工作。例如,后台工作人员可以在完成后将 URL 保存到 DB 中的结果文件(也可以保存更多信息,如当前状态和工作进度),同时网页可以使用 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)或仅使用数据库。使用守护程序,您可以更好地控制正在发生的事情和时间 - 在第一种方法中,您的应用程序可能会触发太多进程。

于 2012-11-30T15:56:58.933 回答