Create a Zip File Using PHP Class Ziparchive Without Writing the File to Disk

Create a zip file using PHP class ZipArchive without writing the file to disk?

Take a look at the following library, it allows creating zip files and returning them as a stream: PHPClasses.org.

Manipulate an Archive in memory with PHP (without creating a temporary file on disk)

I had the same problem but finally found a somewhat obscure solution and decided to share it here.

I came accross the great zip.lib.php/unzip.lib.php scripts which come with phpmyadmin and are located in the "libraries" directory.

Using zip.lib.php worked as a charm for me:

require_once(LIBS_DIR . 'zip.lib.php');

...

//create the zip
$zip = new zipfile();

//add files to the zip, passing file contents, not actual files
$zip->addFile($file_content, $file_name);

...

//prepare the proper content type
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=my_archive.zip");
header("Content-Description: Files of an applicant");

//get the zip content and send it back to the browser
echo $zip->file();

This script allows downloading of a zip, without the need of having the files as real files or saving the zip itself as a file.

It is a shame that this functionality is not part of a more generic PHP library.

Here is a link to the zip.lib.php file from the phpmyadmin source:
https://github.com/phpmyadmin/phpmyadmin/blob/RELEASE_4_5_5_1/libraries/zip.lib.php

UPDATE:
Make sure you remove the following check from the beginning of zip.lib.php as otherwise the script just terminates:

if (! defined('PHPMYADMIN')) {
exit;
}

UPDATE:
This code is available on the CodeIgniter project as well:
https://github.com/patricksavalle/CodeIgniter/blob/439ac3a87a448ae6c2cbae0890c9f672efcae32d/system/helpers/zip_helper.php

how to make zip file downloadable with headers php without saving it on the server

ZIP is not a streamable format (the target needs to support seeking, i.e. a ZIP file cannot be simply written to a target where the previously-written data cannot be re-read and modified) what you are trying to do can't work. So the best solution (if your zip files won't be huge) is creating it in a temporary location, readfile() it and then delete the temporary file.

See the following Stack Overflow questions for further reference. They contain some workarounds that might be fine for you:

  • Zip Stream in PHP
  • LAMP: How to create .Zip of large files for the user on the fly, without disk/CPU thrashing

How to zip a whole folder using PHP

Code updated 2015/04/22.

Zip a whole folder:

// Get real path for our folder
$rootPath = realpath('folder-to-zip');

// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);

// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}

// Zip archive will be created only after closing object
$zip->close();

Zip a whole folder + delete all files except "important.txt":

// Get real path for our folder
$rootPath = realpath('folder-to-zip');

// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Initialize empty "delete list"
$filesToDelete = array();

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);

// Add current file to archive
$zip->addFile($filePath, $relativePath);

// Add current file to "delete list"
// delete it later cause ZipArchive create archive only after calling close function and ZipArchive lock files until archive created)
if ($file->getFilename() != 'important.txt')
{
$filesToDelete[] = $filePath;
}
}
}

// Zip archive will be created only after closing object
$zip->close();

// Delete all files from "delete list"
foreach ($filesToDelete as $file)
{
unlink($file);
}

PHP Zip Creating Class ZipArchive Not Found Error

ZipArchive is apparently not compiled into PHP by default. You need to either recompile it with the '--with-zip=' option or simply install it via PECL.

Here is the manual page explaining the different methods:

http://www.php.net/manual/en/zip.installation.php

unable to create a valid zip file in php using zip archive?

The major reason for this was that there was huge zip file already existing in the same folder with the zip name I used to create a new zip thus due to some reason the new zip was not created and this old huge zip begined to download and as suggested by Marcelo in the comments the size was not mentioned thus downloading wasn't successful but things worked when in declared encoding as binary mentioned the size and changed the zip name or deleted the previous zip file.



Related Topics



Leave a reply



Submit