How to create a ZIP file using PHP and ZipArchive without sending it to the browser?

£可爱£侵袭症+ 提交于 2019-12-12 05:08:21

问题


My PHP/MySQL web application has a function that combines a set of images for each user into a single PDF using ImageMagick. Each PDF is then placed into a ZIP file. Each image can be up to 5 MB in size. My problem is that the browser times out before the user can download the document.

Any ideas on how to best do this?

I was thinking I could create the ZIP file without sending it to the browser (i.e. remove the "headers" at the end of my code) and then email a link to the file; however, it still requires that the user wait a long time for the ZIP file to be created (it appears as if the browser is just hanging). Could this be done with AJAX behind the scenes or directly on the server somehow?

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

回答1:


IMO you should run some background task that will do the job. Background worker can for example save URL to result file in DB after it'll finished (can also save some more information like current status and job progress), meantime webpage can periodically ask server using AJAX if job is already done or not and finally display link when it'll be available.

Simplest way to achieve that is to run your script as background process:

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

archiver.php should begin with following lines:

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

it'll prevent script from being stopped when parent script will finish working.

Second idea I have is more complex - you can write a daemon that will run in background waiting for jobs. To communicate with it you can use queues (like AMQP) or just database. With daemon you'll have more control on what is happening and when - in first approach it can happen that your application will fire too many processes.



来源:https://stackoverflow.com/questions/13619702/how-to-create-a-zip-file-using-php-and-ziparchive-without-sending-it-to-the-brow

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!