phpxmlzipflushon-the-fly

PHP on the fly flush xml to zipfile and push download


I create a xml file based on information from my database (xmltv format). These xml files can be quite big - 25-70mb is normal. Now i create the xml file on the fly like this:

$xmlWriter = new XMLWriter();
$xmlWriter->openURI('php://output');

and flush through the loop to prevent memory overflow. I also set headers to push the content as download:

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $config->filename . '.xml"');

I would like to be able to zip/gzip the xml because of the size. Is this possible on the fly? I have used PHPZip before, which works good with files, but i dont know if i can write the xml output directly to the zip?


Solution

  • If I have understood correctly, the goal is to create gzip compressed data dynamically, without creating a file on the server. This is possible with deflate_init and deflate_add, but requires PHP 7.

    $gzip = deflate_init(ZLIB_ENCODING_GZIP, array('level' => 9));
    $data = deflate_add($gzip, "my", ZLIB_NO_FLUSH);
    $data .= deflate_add($gzip, "data", ZLIB_FINISH);
    

    With deflate_add we can add more data any number of times (the mode should be ZLIB_FINISH for the last chunk).

    We can adjust this method using XMLWriter::openMemory (stores the data in memory) and XMLWriter::flush, to zip the xml elements as they are produced, and create the contents of a .gz file on the fly. For example this code:

    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="file.gz"');
    
    $xmlWriter = new XMLWriter();
    $xmlWriter->openMemory();
    $xmlWriter->startDocument('1.0', 'UTF-8');
    $gzip = deflate_init(ZLIB_ENCODING_GZIP, array('level' => 9));
    
    for ($i = 0; $i < 10; $i++) {
        $xmlWriter->writeElement("element", $i);
        $data = $xmlWriter->outputMemory();
        echo deflate_add($gzip, $data, ZLIB_NO_FLUSH);
    }
    echo deflate_add($gzip, "", ZLIB_FINISH);
    

    creates xml elements, compresses and outputs them one by one, without using too much memory or any files.