Is there a way to compress/archive a folder in the server using php script to .zip or .rar or to any other compressed format, so that on request we could archive the folder and then give the download link
Thanks in advance
Here is an example:
<?php
// Adding files to a .zip file, no zip file exists it creates a new ZIP file
// increase script timeout value
ini_set('max_execution_time', 5000);
// create object
$zip = new ZipArchive();
// open archive
if ($zip->open('my-archive.zip', ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("themes/"));
// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
?>
Beware of a possible problem in Adnan's example: If the target myarchive.zip is inside the the source folder, then you need to exclude it in the loop, or to run the iterator before creating the archive file (if it doesn't exist already). Here's a revised script that uses the latter option, and adds some config vars up top. This one shouldn't be used to add to an existing archive.
<?php
// Config Vars
$sourcefolder = "./" ; // Default: "./"
$zipfilename = "myarchive.zip"; // Default: "myarchive.zip"
$timeout = 5000 ; // Default: 5000
// instantate an iterator (before creating the zip archive, just
// in case the zip file is created inside the source folder)
// and traverse the directory to get the file list.
$dirlist = new RecursiveDirectoryIterator($sourcefolder);
$filelist = new RecursiveIteratorIterator($dirlist);
// set script timeout value
ini_set('max_execution_time', $timeout);
// instantate object
$zip = new ZipArchive();
// create and open the archive
if ($zip->open("$zipfilename", ZipArchive::CREATE) !== TRUE) {
die ("Could not open archive");
}
// add each file in the file list to the archive
foreach ($filelist as $key=>$value) {
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
// close the archive
$zip->close();
echo "Archive ". $zipfilename . " created successfully.";
// And provide download link ?>
<a href="http:<?php echo $zipfilename;?>" target="_blank">
Download <?php echo $zipfilename?></a>
PHP comes with the ZipArchive extension, which is just right for you.
Related
I have a folder in my web server were I put zip files that I need to then unzip. I want to do that with php and this is what I have tried but it does not work:
<?php
$file = $_GET["file"];
$zip = new ZipArchive;
$res = $zip->open($file+'.zip');
$zip->extractTo('./');
$zip->close();
?>
The zip files are in the same folder as the php file, but when I go to the php page it does nothing.
By doing some testing I have found out that the script dies on the $zip = new ZipArchive; line
How can I manage this to work?
<?php
$fileName = $_GET['file']; // get file name in the URL param "file"
if (isset($fileName)) { // if $fileName php variable is set than
$zip = new ZipArchive; // create object
$res = $zip->open($fileName); // open archive
if ($res === TRUE) {
$zip->extractTo('./'); // extract contents to destination directory
$zip->close(); //close the archieve
echo 'Extracted file "'.$fileName.'"';
} else {
echo 'Cannot find the file name "'.$fileName.'" (the file name should include extension (.zip, ...))';
}
}
else {
echo 'Please set file name in the "file" param';
}
?>
Note:- For More Details Please refer https://www.php.net/manual/en/class.ziparchive.php
I have found the problem.
The code is fine, but the hosting service is not, and they do not have the ZIP extension available right now
Try this code. Also change $zip->open($file+".zip"); to $zip->open($file);.
+ (plus sign) is not concatenation operator in php
<?php
// $_GET["file"] is set to `a.zip`
$file = $_GET["file"];
$zip = new ZipArchive;
$res = $zip->open($file);
$zip->extractTo('./');
$zip->close();
?>
I am using the function below to compress files, but in each directory it can automatically add two files as shown below (red Delineating).
How do I compress files while excluding these unwanted files?
function ziparchive($name,$folder){
// create object
$ziparchivename= $name.'.zip';
//echo $ziparchivename;
$zip = new ZipArchive();
// open archive
if ($zip->open($ziparchivename, ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder));
// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
}
Some thing like this should work.
$skipFiles = array('.', '..');
foreach ($iterator as $key=>$value) {
if(!in_array($key, $skipFiles)){
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
php manual in_array
Another place to search is the array_search.
Another place to search is the array_search.
I'm a PHP novice and so looking for some advice on a PHP function i have created to use within a Wordpress installation.
As you can see from the code below, it runs when one of the admin's press 'Publish' on a pending post.
It takes a Zip file that has been uploaded by a user via Gravity Forms, then unzips ONLY .mp3 extensions. Re-zips and moves all the files to a new folder in our Amazon S3 directory.
The code is pieced together from my limited knowledge and some help along the way with questions on here.
So, here's what i ended up with:
add_action('pending_to_publish', 'unzip_to_s3');
function unzip_to_s3() {
global $post;
global $wpdb;
// Only run function if post is portfolio post type
if ('portfolio' == $post->post_type) {
// Set temp path
$temp_path = '../wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/tmp/';
// Get filename from Zip file
$file = get_post_meta($post->ID, 'file_url', true);
$zip_file = basename($file);
// Create full Zip file path
$zip_file_path = $temp_path.$zip_file;
// Generate unique name for temp sub_folder for unzipped files
$temp_unzip_folder = uniqid('temp_TMS_', true);
// Create full temp sub_folder path
$temp_unzip_path = $temp_path.$temp_unzip_folder;
// Make the new temp sub_folder for unzipped files
if (!mkdir($temp_unzip_path, 0755, true)) {
die('Error: Could not create path: '.$temp_unzip_path);
}
// Unzip files to temp unzip folder, ignoring anything that is not a .mp3 extension
$zip = new ZipArchive();
$filename = $zip_file_path;
if ($zip->open($filename)!==TRUE) {
exit("cannot open <$filename>\n");
}
for ($i=0; $i<$zip->numFiles;$i++) {
$info = $zip->statIndex($i);
$file = pathinfo($info['name']);
if(strtolower($file['extension']) == "mp3") {
file_put_contents($temp_unzip_path.'/'.basename($info['name']), $zip->getFromIndex($i));
} else {
$zip->deleteIndex($i);
}
}
$zip->close();
// Re-zip the unzipped mp3's and store new zip file in temp folder created earlier
$temp_unzip_path = $temp_unzip_path.'/';
$zip = new ZipArchive();
$dirArray = array();
$new_zip_file = $temp_unzip_path.$zip_file;
$new = $zip->open($new_zip_file, ZIPARCHIVE::CREATE);
if ($new === true) {
$handle = opendir($temp_unzip_path);
while (false !== ($entry = readdir($handle))) {
if(!in_array($entry,array('.','..')))
{
$dirArray[] = $entry;
$zip->addFile($temp_unzip_path.$entry,$entry);
}
}
closedir($handle);
} else {
echo 'Failed to create Zip';
}
$zip->close();
// Set Media bucket dir
$bucket_path = '../wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/mixtape2/';
// Generate unique name for sub_bucket
$sub_bucket = uniqid('TMS_', true);
// Create full sub_bucket path
$sub_bucket_path = $bucket_path.$sub_bucket;
// Make the new sub_bucket
if (!mkdir($sub_bucket_path, 0755, true)) {
die('Error: Could not create path: '.$sub_bucket_path);
}
// Move mp3's to new sub_bucket
// Get array of all source files
$files = scandir($temp_unzip_path);
// Identify directories
$source = $temp_unzip_path;
$destination = $sub_bucket_path.'/';
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// if move files is successful delete the original temp folder
if (rename($source.$file, $destination.$file)) {
rmdir($temp_unzip_path);
}
}
// Delete original Zip file
unlink($temp_path.$zip_file);
// Update Custom field for new Zip file location
update_post_meta($post->ID, 'file_url', 'http://themixtapesite.com/wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/mixtape2/'.$sub_bucket.'/'.$zip_file);
}
}
Whilst this function does work, we're dealing with large files and so it does take a while to process...
What is happening is when the admin presses publish it triggers this function but the page just sits there until it's finished this function and then will continue. This function can take upto around 5 minutes to run.
I'm looking to optimise this function (in terms of code) but also see if there's a way i can run this in the background so that the admin can carry on with other things and not have to sit there waiting around.
Any help appreciated.
You may want to try to WP cron and schedule the task at that point so that it runs in the background. Here is some resources for that. the basic concept would go something like this.
if ( ! wp_next_scheduled( 'pending_to_publish' ) ) {
wp_schedule_single_event($timestamp,'pending_to_publish');
}
add_action('pending_to_publish', 'unzip_to_s3');
http://wpengineer.com/1908/use-wordpress-cron/
http://codex.wordpress.org/Category%3aWP-Cron_Functions
https://wordpress.stackexchange.com/questions/42694/run-a-cron-job-or-similar-in-the-background-of-wp-after-post-update-create
I am using this code to read a protected directory (username&password) contents called (protect).
<?php
require_once("admin/global.inc.php");
// increase script timeout value
ini_set('max_execution_time', 300);
//Generate a new flag
$random = (rand(000000,999999));
$date = date("y-m-d");
// create object
$zip = new ZipArchive();
// open archive
if ($zip->open("$date-$random.zip", ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("protect/")); //check question #2
// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
if ($key != 'protect/.htaccess')
{
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
$query="INSERT INTO `archives_logs` (`id`, `file`, `flag`, `date`) VALUES (NULL, '$key', '$random', '$date')";
$query_result = mysql_query ($query);
}
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
?>
If I place my code file in a location differerent than the protected directory location, i have to change the path of the directory to be compressed which is fine, BUT the problem is that all directories in the path are included in the Zip Archive.
So if open the compressed file i get: www/username/public_html/etc...
Here is the directories strcuture:
www/protect/(files to be compressed here)
www/compress_code.php (here is my current code file)
The path that I wish to place my code file in is:
www/protect/admin/files/compress_code.php
Q1) How do I keep my code file in the last mentioned location WITHOUT including the path in my ZipArchive file?
Q2) When my code is in the same location of the directory to be compressed, and when i open the compressed file i see, protect/(the files). Can I add only the content of protect directory in the Zip Archive without inclduing the directory itself?
It's pretty simple:
Store the target path in a variable.
Remove target path from the localname before adding the file.
Like this:
$flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::SKIP_DOTS;
$target = 'protect/';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target, $flags));
foreach ($iterator as $key=>$value) {
if ($key != "{$target}.htaccess")
{
$localname = substr($key, strlen($target));
$zip->addFile($key, $localname) or die ("ERROR: Could not add file: $key");
}
}
This should actually answers both of your questions.
I want the code to make all files in the tree to .zip files in the root
<?PHP
// create object
$zip = new ZipArchive();
// open archive
if ($zip->open('my-archive.zip', ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
// list of files to add
// list of files to add
$fileList = array(
'im/asd.pdf',
'im/df.pdf',
'im/d/qoyyum.txt'
);
// add files
foreach ($fileList as $f) {
$zip->addFile($f) or die ("ERROR: Could not add file: $f");
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
?>
for example folder /im contains
/im/asd.pdf
/im/df.pdf
/im/d/qoyyum.txt
the 'my-archive.zip' extract should look like this
my-archive/asd.pdf
my-archive/df.pdf
my-archive/qoyyum.txt
I want to prevent the folder hierarchy when extracting the zip. so that every files should be in the root of the extracted zip folder
please suggest a tip to do
There's a second parameter in ZipArchive::addFile() called localname (see here) which lets you set the local name of the file within the zip archive. Use this to override the directory structure which is the default.
foreach ($fileList as $f) {
$filename_parts = explode('/', $f); // Split the filename up by the '/' character
$zip->addFile($f, end($filename_parts)) or die ("ERROR: Could not add file: $f");
}