How to compress a folder in yii2 web app into a zip? - php

I am trying to zip a folder.
This is the function in ExportarController.php
public function zipping(){
$rootPath = realpath('results/');
// Initialize archive object
$zip = new \ZipArchive();
$zip->open('../web/descargas/Region.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);
}
}
It worked pefectly when I tried it outside yii2 webapp. But when I added the function to yii2 controller I got the error:
Class 'app\controllers\ZipArchive' not found
Do you know what is going wrong? does it have something to do with the directory I'm trying to write in?
Please help me.
Thank you so much.
SOLUTION
It was cuz of the namespace, I had to ad \ to every ziparchive function.
Like \ZipArchive() and \ZipArchive::CREATE | \ZipArchive::OVERWRITE
Thanks to all of you.

First enable php zip extension
$zip = new \ZipArchive();
$test = tempnam(sys_get_temp_dir(), rand(0, 999999999) . '.zip');
var_dump($test);
$res = $zip->open($test, \ZipArchive::CREATE);
if ($res) {
foreach ($csv_data as $data) {
$zip->addFile($data['file_name'],'chat_'. $data['chatID'] .'.csv');
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=chat_' . date('Ymd_His'). '.zip');
readfile($test);
} else {
echo 'zip error';
die;
}
Read for More : http://php.net/manual/en/class.ziparchive.php

Related

How to protect-password zipped file in PHP

zipping the video files works fine, but I want to add a password to a zipped file instead of individual files that have been zipped. Below is my code:
public function zipVideos()
{
$videos_zip = "videos.zip";
$zip = new ZipArchive();
$zip->open($videos_zip, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->setPassword('secret');
$path = $this->getPath("videos");
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
foreach ($files as $name => $file) {
if (file_exists($file)) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$relativePath = "videos" . DIRECTORY_SEPARATOR . basename($filePath, strlen($path) + 1);
$zip->addFile($filePath, $relativePath);
// I don't want this individual video file to be password-protected
$zip->setEncryptionName($relativePath, ZipArchive::EM_AES_256);
}
}
}
// A file i want to be password-protected should be the zipped file - videos.zip itself instead
$zip->setEncryptionName($videos_zip, ZipArchive::EM_AES_256);
$zip->close();
return redirect("/media")->banner("All videos have been zipped successfully");
}
I need your guide. Thanks in advance
NB: Please I use Laravel framework.

How to combine pdfs generated by fpdi in different php files into one zip file [duplicate]

I have found here at stackoveflow some code on how to ZIP a specific file, but how about a specific folder?
Folder/
index.html
picture.jpg
important.txt
inside in My Folder, there are files. after zipping the My Folder, i also want to delete the whole content of the folder except important.txt.
Found this here at stack
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);
}
There is a useful undocumented method in the ZipArchive class: addGlob();
$zipFile = "./testZip.zip";
$zipArchive = new ZipArchive();
if ($zipArchive->open($zipFile, (ZipArchive::CREATE | ZipArchive::OVERWRITE)) !== true)
die("Failed to create archive\n");
$zipArchive->addGlob("./*.txt");
if ($zipArchive->status != ZIPARCHIVE::ER_OK)
echo "Failed to write files to zip\n";
$zipArchive->close();
Now documented at: www.php.net/manual/en/ziparchive.addglob.php
I assume this is running on a server where the zip application is in the search path. Should be true for all unix-based and I guess most windows-based servers.
exec('zip -r archive.zip "My folder"');
unlink('My\ folder/index.html');
unlink('My\ folder/picture.jpg');
The archive will reside in archive.zip afterwards. Keep in mind that blanks in file or folder names are a common cause of errors and should be avoided where possible.
Try this:
$zip = new ZipArchive;
$zip->open('myzip.zip', ZipArchive::CREATE);
foreach (glob("target_folder/*") as $file) {
$zip->addFile($file);
if ($file != 'target_folder/important.txt') unlink($file);
}
$zip->close();
This will not zip recursively though.
I tried with the code below and it is working. The code is self explanatory, please let me know if you have any questions.
<?php
class FlxZipArchive extends ZipArchive
{
public function addDir($location, $name)
{
$this->addEmptyDir($name);
$this->addDirDo($location, $name);
}
private function addDirDo($location, $name)
{
$name .= '/';
$location .= '/';
$dir = opendir ($location);
while ($file = readdir($dir))
{
if ($file == '.' || $file == '..') continue;
$do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
$this->$do($location . $file, $name . $file);
}
}
}
?>
<?php
$the_folder = '/path/to/folder/to/be/zipped';
$zip_file_name = '/path/to/zip/archive.zip';
$za = new FlxZipArchive;
$res = $za->open($zip_file_name, ZipArchive::CREATE);
if($res === TRUE)
{
$za->addDir($the_folder, basename($the_folder));
$za->close();
}
else{
echo 'Could not create a zip archive';
}
?>
This is a function that zips a whole folder and its contents in to a zip file and you can use it simple like this :
addzip ("path/folder/" , "/path2/folder.zip" );
function :
// compress all files in the source directory to destination directory
function create_zip($files = array(), $dest = '', $overwrite = false) {
if (file_exists($dest) && !$overwrite) {
return false;
}
if (($files)) {
$zip = new ZipArchive();
if ($zip->open($dest, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach ($files as $file) {
$zip->addFile($file, $file);
}
$zip->close();
return file_exists($dest);
} else {
return false;
}
}
function addzip($source, $destination) {
$files_to_zip = glob($source . '/*');
create_zip($files_to_zip, $destination);
echo "done";
}
Use this function:
function zip($source, $destination)
{
if (!extension_loaded('zip') || !file_exists($source)) {
return false;
}
$zip = new ZipArchive();
if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
return false;
}
$source = str_replace('\\', '/', realpath($source));
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = str_replace('\\', '/', $file);
// Ignore "." and ".." folders
if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
continue;
}
$file = realpath($file);
if (is_dir($file) === true) {
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
} elseif (is_file($file) === true) {
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
} elseif (is_file($source) === true) {
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
Example use:
zip('/folder/to/compress/', './compressed.zip');
Why not Try EFS PhP-ZiP MultiVolume Script ... I zipped and transferred hundreds of gigs and millions of files ... ssh is needed to effectively create archives.
But i belive that resulting files can be used with exec directly from php:
exec('zip -r backup-2013-03-30_0 . -i#backup-2013-03-30_0.txt');
I do not know if it works. I have not tried ...
"the secret" is that the execution time for archiving should not exceed the time allowed for execution of PHP code.
This is a working example of making ZIPs in PHP:
$zip = new ZipArchive();
$zip_name = time().".zip"; // Zip name
$zip->open($zip_name, ZipArchive::CREATE);
foreach ($files as $file) {
echo $path = "uploadpdf/".$file;
if(file_exists($path)){
$zip->addFromString(basename($path), file_get_contents($path));---This is main function
}
else{
echo"file does not exist";
}
}
$zip->close();
If you have subfolders and you want to preserve the structure of the folder do this:
$zip = new \ZipArchive();
$fileName = "my-package.zip";
if ($zip->open(public_path($fileName), \ZipArchive::CREATE) === true)
{
$files = \Illuminate\Support\Facades\File::allFiles(
public_path('/MY_FOLDER_PATH/')
);
foreach ($files as $file) {
$zip->addFile($file->getPathname(), $file->getRelativePathname());
}
$zip->close();
return response()
->download(public_path($fileName))
->deleteFileAfterSend(true);
}
deleteFileAfterSend(true) to delete the file my-package.zip from the server.
Don't forget to change /MY_FOLDER_PATH/ with the path of your folder that you want to download.
This will resolve your issue. Please try it.
$zip = new ZipArchive;
$zip->open('testPDFZip.zip', ZipArchive::CREATE);
foreach (glob(APPLICATION_PATH."pages/recruitment/uploads/test_pdf_folder/*") as $file) {
$new_filename = end(explode("/",$file));
$zip->addFile($file,"emp/".$new_filename);
}
$zip->close();
I found this post in google as the second top result, first was using exec :(
Anyway, while this did not suite my needs exactly.. I decided to post an answer for others with my quick but extended version of this.
SCRIPT FEATURES
Backup file naming day by day, PREFIX-YYYY-MM-DD-POSTFIX.EXTENSION
File Reporting / Missing
Previous Backups Listing
Does not zip / include previous backups ;)
Works on windows/linux
Anyway, onto the script.. While it may look like a lot.. Remember there is excess in here.. So feel free to delete the reporting sections as needed...
Also it may look messy as well and certain things could be cleaned up easily... So dont comment about it, its just a quick script with basic comments thrown in.. NOT FOR LIVE USE.. But easy to clean up for live use!
In this example, it is run from a directory that is inside of the root www / public_html folder.. So only needs to travel up one folder to get to the root.
<?php
// DIRECTORY WE WANT TO BACKUP
$pathBase = '../'; // Relate Path
// ZIP FILE NAMING ... This currently is equal to = sitename_www_YYYY_MM_DD_backup.zip
$zipPREFIX = "sitename_www";
$zipDATING = '_' . date('Y_m_d') . '_';
$zipPOSTFIX = "backup";
$zipEXTENSION = ".zip";
// SHOW PHP ERRORS... REMOVE/CHANGE FOR LIVE USE
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
// ############################################################################################################################
// NO CHANGES NEEDED FROM THIS POINT
// ############################################################################################################################
// SOME BASE VARIABLES WE MIGHT NEED
$iBaseLen = strlen($pathBase);
$iPreLen = strlen($zipPREFIX);
$iPostLen = strlen($zipPOSTFIX);
$sFileZip = $pathBase . $zipPREFIX . $zipDATING . $zipPOSTFIX . $zipEXTENSION;
$oFiles = array();
$oFiles_Error = array();
$oFiles_Previous = array();
// SIMPLE HEADER ;)
echo '<center><h2>PHP Example: ZipArchive - Mayhem</h2></center>';
// CHECK IF BACKUP ALREADY DONE
if (file_exists($sFileZip)) {
// IF BACKUP EXISTS... SHOW MESSAGE AND THATS IT
echo "<h3 style='margin-bottom:0px;'>Backup Already Exists</h3><div style='width:800px; border:1px solid #000;'>";
echo '<b>File Name: </b>',$sFileZip,'<br />';
echo '<b>File Size: </b>',$sFileZip,'<br />';
echo "</div>";
exit; // No point loading our function below ;)
} else {
// NO BACKUP FOR TODAY.. SO START IT AND SHOW SCRIPT SETTINGS
echo "<h3 style='margin-bottom:0px;'>Script Settings</h3><div style='width:800px; border:1px solid #000;'>";
echo '<b>Backup Directory: </b>',$pathBase,'<br /> ';
echo '<b>Backup Save File: </b>',$sFileZip,'<br />';
echo "</div>";
// CREATE ZIPPER AND LOOP DIRECTORY FOR SUB STUFF
$oZip = new ZipArchive;
$oZip->open($sFileZip, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$oFilesWrk = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathBase),RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($oFilesWrk as $oKey => $eFileWrk) {
// VARIOUS NAMING FORMATS OF THE CURRENT FILE / DIRECTORY.. RELATE & ABSOLUTE
$sFilePath = substr($eFileWrk->getPathname(),$iBaseLen, strlen($eFileWrk->getPathname())- $iBaseLen);
$sFileReal = $eFileWrk->getRealPath();
$sFile = $eFileWrk->getBasename();
// WINDOWS CORRECT SLASHES
$sMyFP = str_replace('\\', '/', $sFileReal);
if (file_exists($sMyFP)) { // CHECK IF THE FILE WE ARE LOOPING EXISTS
if ($sFile!="." && $sFile!="..") { // MAKE SURE NOT DIRECTORY / . || ..
// CHECK IF FILE HAS BACKUP NAME PREFIX/POSTFIX... If So, Dont Add It,, List It
if (substr($sFile,0, $iPreLen)!=$zipPREFIX && substr($sFile,-1, $iPostLen + 4)!= $zipPOSTFIX.$zipEXTENSION) {
$oFiles[] = $sMyFP; // LIST FILE AS DONE
$oZip->addFile($sMyFP, $sFilePath); // APPEND TO THE ZIP FILE
} else {
$oFiles_Previous[] = $sMyFP; // LIST PREVIOUS BACKUP
}
}
} else {
$oFiles_Error[] = $sMyFP; // LIST FILE THAT DOES NOT EXIST
}
}
$sZipStatus = $oZip->getStatusString(); // GET ZIP STATUS
$oZip->close(); // WARNING: Close Required to append files, dont delete any files before this.
// SHOW BACKUP STATUS / FILE INFO
echo "<h3 style='margin-bottom:0px;'>Backup Stats</h3><div style='width:800px; height:120px; border:1px solid #000;'>";
echo "<b>Zipper Status: </b>" . $sZipStatus . "<br />";
echo "<b>Finished Zip Script: </b>",$sFileZip,"<br />";
echo "<b>Zip Size: </b>",human_filesize($sFileZip),"<br />";
echo "</div>";
// SHOW ANY PREVIOUS BACKUP FILES
echo "<h3 style='margin-bottom:0px;'>Previous Backups Count(" . count($oFiles_Previous) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
foreach ($oFiles_Previous as $eFile) {
echo basename($eFile) . ", Size: " . human_filesize($eFile) . "<br />";
}
echo "</div>";
// SHOW ANY FILES THAT DID NOT EXIST??
if (count($oFiles_Error)>0) {
echo "<h3 style='margin-bottom:0px;'>Error Files, Count(" . count($oFiles_Error) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
foreach ($oFiles_Error as $eFile) {
echo $eFile . "<br />";
}
echo "</div>";
}
// SHOW ANY FILES THAT HAVE BEEN ADDED TO THE ZIP
echo "<h3 style='margin-bottom:0px;'>Added Files, Count(" . count($oFiles) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
foreach ($oFiles as $eFile) {
echo $eFile . "<br />";
}
echo "</div>";
}
// CONVERT FILENAME INTO A FILESIZE AS Bytes/Kilobytes/Megabytes,Giga,Tera,Peta
function human_filesize($sFile, $decimals = 2) {
$bytes = filesize($sFile);
$sz = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . #$sz[$factor];
}
?>
WHAT DOES IT DO??
It will simply zip the complete contents of the variable $pathBase and store the zip in that same folder. It does a simple detection for previous backups and skips them.
CRON BACKUP
This script i've just tested on linux and worked fine from a cron job with using an absolute url for the pathBase.
Use this is working fine.
$dir = '/Folder/';
$zip = new ZipArchive();
$res = $zip->open(trim($dir, "/") . '.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
if ($res === TRUE) {
foreach (glob($dir . '*') as $file) {
$zip->addFile($file, basename($file));
}
$zip->close();
} else {
echo 'Failed to create to zip. Error: ' . $res;
}
Create a zip folder in PHP.
Zip create method
public function zip_creation($source, $destination){
$dir = opendir($source);
$result = ($dir === false ? false : true);
if ($result !== false) {
$rootPath = realpath($source);
// Initialize archive object
$zip = new ZipArchive();
$zipfilename = $destination.".zip";
$zip->open($zipfilename, 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();
return TRUE;
} else {
return FALSE;
}
}
Call the zip method
$source = $source_directory;
$destination = $destination_directory;
$zipcreation = $this->zip_creation($source, $destination);
I did some small improvement in the script.
<?php
$directory = "./";
//create zip object
$zip = new ZipArchive();
$zip_name = time().".zip";
$zip->open($zip_name, ZipArchive::CREATE);
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
$path = $file->getRealPath();
//check file permission
if(fileperms($path)!="16895"){
$zip->addFromString(basename($path), file_get_contents($path)) ;
echo "<span style='color:green;'>{$path} is added to zip file.<br /></span> " ;
}
else{
echo"<span style='color:red;'>{$path} location could not be added to zip<br /></span>";
}
}
$zip->close();
?>
For anyone reading this post and looking for a why to zip the files using addFile instead of addFromString, that does not zip the files with their absolute path (just zips the files and nothing else), see my question and answer here
If you are sure you are doing everything correctly and it is still not working. Check your PHP (user) permissions.
My 2 cents :
class compressor {
/**
* public static $NOT_COMPRESS
* use: compressor::$NOT_COMPRESS
* no compress thoses files for upload
*/
public static $NOT_COMPRESS = array(
'error_log',
'cgi-bin',
'whatever/whatever'
);
/**
* end public static $NOT_COMPRESS
*/
/**
* public function compress_folder( $dir, $version, $archive_dest );
* #param {string} $dir | absolute path to the directory
* #param {string} $version_number | ex: 0.1.1
* #param {string} $archive_dest | absolute path to the future compressed file
* #return {void} DO A COMPRESSION OF A FOLDER
*/
public function compress_folder( $dir, $version, $archive_dest ){
// name of FUTURE .zip file
$archive_name = $version_number.'.zip';
// test dir exits
if( !is_dir($dir) ){ exit('No temp directory ...'); }
// Iterate and archive API DIRECTORIES AND FOLDERS
// create zip archive + manager
$zip = new ZipArchive;
$zip->open( $archive_dest,
ZipArchive::CREATE | ZipArchive::OVERWRITE );
// iterator / SKIP_DOTS -> ignore '..' and '.'
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $dir,
RecursiveDirectoryIterator::SKIP_DOTS )
);
// loop iterator
foreach( $it as $file ){
// check files not to add for compress
// loop list for not add to upload .zip
foreach( compressor::$NOT_COMPRESS as $k => $v) {
if( preg_match( '/^('.preg_quote($v,'/').')/', $it->getSubPathName() ) == true ){
// break this loop and parent loop
continue 2;
}
}
// end loop list
// for Test
// echo $it->getSubPathName()."\r\n";
// no need to check if is a DIRECTORY with $it->getSubPathName()
// DIRECTORIES are added automatically
$zip->addFile( $it->getPathname(), $it->getSubPathName() );
}
// end loop
$zip->close();
// END Iterate and archive API DIRECTORIES AND FOLDERS
}
/**
* public function compress_folder( $version_number );
*/
}
// end class compressor
use :
// future name of the archive
$version = '0.0.1';
// path of directory to compress
$dir = $_SERVER['DOCUMENT_ROOT'].'/SOURCES';
// real path to FUTURE ARCHIVE
$archive_dest = $_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/'.$version.'.zip';
$Compress = new compressor();
$Compress->compress_folder( $dir, $version, $archive_dest );
// this create a .zip file like :
$_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/0.0.1.zip
This is the best solution for me which is working fine in my Codecanyon project and well tested.
function zipper($space_slug)
{
// Get real path for our folder
$rootPath = realpath('files/' . $space_slug);
// Initialize archive object
$zip = new ZipArchive();
/* Opening the zip file and creating it if it doesn't exist. */
$zip->open('files/' . $space_slug . '.zip', ZipArchive::CREATE |
ZipArchive::OVERWRITE);
// Create recursive directory iterator
/** #var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::SELF_FIRST
);
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();
}
includes all sub-folders:
zip_folder('path/to/input/folder', 'path/to/output_zip_file.zip') ;
Here is source-code (there might have been an update, but below I put the copy of that code):
function zip_folder ($input_folder, $output_zip_file) {
$zipClass = new ZipArchive();
if($input_folder !== false && $output_zip_file !== false)
{
$res = $zipClass->open($output_zip_file, \ZipArchive::CREATE);
if($res === TRUE) {
// Add a Dir with Files and Subdirs to the archive
$foldername = basename($input_folder);
$zipClass->addEmptyDir($foldername);
$foldername .= '/'; $input_folder .= '/';
// Read all Files in Dir
$dir = opendir ($input_folder);
while ($file = readdir($dir)) {
if ($file == '.' || $file == '..') continue;
// Rekursiv, If dir: GoodZipArchive::addDir(), else ::File();
$do = (filetype( $input_folder . $file) == 'dir') ? 'addDir' : 'addFile';
$zipClass->$do($input_folder . $file, $foldername . $file);
}
$zipClass->close();
}
else { exit ('Could not create a zip archive, migth be write permissions or other reason. Contact admin.'); }
}
}

How to ZIP an entire folder in PHP, even the empty ones? [duplicate]

This question already has answers here:
How to zip a whole folder using PHP
(20 answers)
Closed 1 year ago.
I'm trying to download a zip from a folder that i have on my app (Laravel 5.8), it's working but they skip all empty folders, and I need them in the zip.
I already tried ZipArchive (php) and chumper/zipper from composer.
Any idea of how can i do this?
This is a Linux Server, running MySQL 5, PHP 7.2 and Apache2.
$files = glob($folder_path);
\Zipper::make($folder_path.'/'.$folder_main_name.'.zip')->add($files)->close();
This lib only accepts glob, but if you have any solution that works, i can easily abandon this.
// Initialize archive object
$zip = new ZipArchive();
$zip->open($zipFilename, 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)
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
if (!$file->isDir())
{
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}else {
if($relativePath !== false)
$zip->addEmptyDir($relativePath);
}
}
// Zip archive will be created only after closing object
$zip->close();
Hi. I modified the previous answer and now I get the zip file including the empty folders. I hope this helps.
// 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)
{
// Is this a directory?
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);
}
else {
$end2 = substr($file,-2);
if ($end2 == "/.") {
$folder = substr($file, 0, -2);
$zip->addEmptyDir($folder);
}
}
}
// Zip archive will be created only after closing object
$zip->close();
** Try this. Off of the top of my head, not tested. But its the general idea.

Move or Delete and Force download of Archive after creation

To put it simply, I would like my users to be able to download their website files, so I created a "Download Website" button which uses this script to add all files/folders in their directory which is in the variable $direc and archive those files/folders.
<?
///////// DOWNLOAD ENTIRE WEBSITE:
if(isset($_POST['download_site'])){
// define some basics
$rootPath = '../useraccounts/'.$direc.'';
$archiveName = ''.$direc.'.zip';
// initialize the ZIP archive
$zip = new ZipArchive;
$zip->open($archiveName, ZipArchive::CREATE);
// create recursive directory iterator
$files = new RecursiveIteratorIterator (new RecursiveDirectoryIterator($rootPath), RecursiveIteratorIterator::LEAVES_ONLY);
// let's iterate
foreach ($files as $name => $file) {
$filePath = $file->getRealPath();
$zip->addFile($filePath);
}
// close the zip file
if (!$zip->close()) {
echo '<p>There was a problem writing the ZIP archive.</p>';
} else {
echo '<p>Successfully created the ZIP Archive!</p>';
}
}
?>
To my surprise, this code works. Although, there are a few hiccups:
It doesn't automatically force a download of that archive.
It adds the archive in to my main directory rather than moving it to a separate directory of my choice such as site_downloads or deletes it up on completed download.
Are these problems at all fixable or if not, is there a better way to do it so my main directory does not get filled with constant downloads? I guess it will cause a problem once a Archive is created more than once, as it uses the Directory name.
Solved this by using a few different combinations:
<?
///////// DOWNLOAD ENTIRE WEBSITE:
if(isset($_POST['download_site'])){
// define some basics
$rootPath = '../useraccounts/'.$direc.'';
$archiveName = ''.$direc.'.zip';
// initialize the ZIP archive
$zip = new ZipArchive;
$zip->open($archiveName, ZipArchive::CREATE);
// create recursive directory iterator
$files = new RecursiveIteratorIterator (new RecursiveDirectoryIterator($rootPath), RecursiveIteratorIterator::LEAVES_ONLY);
// let's iterate
foreach ($files as $name => $file) {
$filePath = $file->getRealPath();
$zip->addFile($filePath);
}
// close the zip file
if (!$zip->close()) {
echo '<p>There was a problem writing the ZIP archive.</p>';
} else {
rename($archiveName, 'user_archives/'.$archiveName.'');
$yourfile = "user_archives/".$archiveName."";
$file_name = basename($yourfile);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=$file_name");
header("Content-Length: " . filesize($yourfile));
readfile($yourfile);
ignore_user_abort(true);
if (connection_aborted()) {
unlink('user_archives/'.$archiveName.'');
} else {
unlink('user_archives/'.$archiveName.'');
}
echo '<p>Successfully created the ZIP Archive!</p>';
}
}
?>
This seems to fix all problems.

How to create Zip file and download in CakePhp?

I'm trying to create zip files using CakePhp 1.3. The file descriptions are stored in database. In my controller I'm using the following logic.
// Fetching File description form database.
$this->view = 'Media';
$user_id=$this->Session->read('userData.User.id');
$condition = "Document.isdeleted = '0' AND Document.project_id='". $project_id."'";
$projectDocumentList = $this->Document->find("all",array('conditions'=>$condition,'fields'=>array('Document.id','Document.document_name','Document.path'),'order' => array('Document.id ASC')));
$this->set('projectDocumentList',$projectDocumentList);
if(!empty($projectDocumentList)){
$fileNames = "";
$fileNamesArr = array();
foreach($projectDocumentList as $projectDocument){
$fileNamesArr[ ]= $projectDocument['Document']['document_name'];
}
}
// Making zip
$archive_file_name='myFile.zip';
$file_path= "my_file_path";// Here I'm using my server basepath
$zip = new ZipArchive();
if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
exit("cannot open <$archive_file_name>\n");
}
foreach($fileNamesArr as $files)
{
$zip->addFile($file_path.$files,$files);
//echo $file_path.$files."<br>"; // This can show the file in browser
}
$zip->close();
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Pragma: no-cache");
header("Expires: 0");
readfile("$archive_file_name");
exit;
Now the zip file download as myFile.zip, but when I'm going to open that file, it throws an error "The archive is either in unknown format or damaged".
Create Zip File of 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();
And than pass the path of the zip file to the view.
$this->set('Zip_path'.zip_file_name);

Categories