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?
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.