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");
}
Related
I'm creating a online widget creation tool in PHP, and I am able to export everything I need via .zip , just the problem is that users have to extract the zip and then add the .wdgt extension on the folder for it to work in iBooks. Is there any way I could make this part of the process easier, e.g - just unzip and the .wdgt folder is there, or even better, download as .wdgt.
Here is the code I have to create a ZIP file:
//zip name
$archiveName = 'widget.zip';
$fileNames = array();
//scan through directories, and add to array
foreach(scandir($workingDir) as $content){
$fileNames[] = $workingDir.$content;
}
foreach(scandir($resources) as $content){
$fileNames[] = $resources.$content;
}
archiveFiles($fileNames, $archiveName);
function archiveFiles($fileNames, $archiveName){
//init new ZipArchive()
$zip = new ZipArchive();
//open archive
$zip->open($archiveName);
if($zip->open($archiveName, ZIPARCHIVE::OVERWRITE ) !==TRUE){
exit("Cannot open <$archiveName>\n");
}
else{
//archive create, now add files
foreach($fileNames as $files){
if('.' === $files || '..' === $files) continue;
//get just the filename and extension
$fileName = explode("/", $files);
$num = (count($fileName) - 1);
$theFilename = $fileName[$num];
//add file into the archive - full path of file, new filename
$zip->addFile($files,$theFilename);
}
$zip->close();
header( 'Location: http://MYURL/'.$archiveName ) ; //Redirects to the zip archive
exit;
}
}
This works fine. I just need to be able to either just download a .wdgt folder with the content I need in it, or be able to ZIP up a .wdgt folder that has the content that I need.
I have tried changing $archiveName to $archiveName = "widget.wdgt.zip"; and $archiveName = "widget.wdgt";
The $archiveName = "widget.wdgt.zip"; was able to unzip fine on Windows. Although on the MAC is just gave an error. And It has to work on the MAC as it is in iBook's Author these widgets will work on
Managed to get a .wdgt folder downloaded within a zip file, all that I needed to do was when adding the file in the loop was this:
$zip->addFile($files, 'MYWIDGET.wdgt/'.$theFilename);
by adding the 'MYWIDGET.wdgt/'.$theFilename path into the addFile() it forced ZipArchive to create a MYWIDGET.wdgt folder and adding the files into it.
I'm writing a PHP script that archives a selected directory and all its sub-folders. The code works fine, however, I'm running into a small problem with the structure of my archived file.
Imagine the script is located in var/app/current/example/two/ and that it wants to backup everything plus its sub directories starting at var/app/current
When I run the script it creates an archive with the following structure:
/var/app/current/index.html
/var/app/current/assets/test.css
/var/app/current/example/file.php
/var/app/current/example/two/script.php
Now I was wondering how:
a) How can I remove the /var/app/current/ folders so that the root directory of the archive starts beyond the folder current, creating the following structure:
index.html
assets/test.css
example/file.php
example/two/script.php
b) Why & how can I get rid of the "/" before the folder var?
//Create ZIP file
$zip = new ZipArchive();
$tmpzip = realpath(dirname(__FILE__))."/".substr(md5(TIME_NOW), 0, 10).random_str(54).".zip";
//If ZIP failed
if($zip->open($tmpzip,ZIPARCHIVE::CREATE)!== TRUE)
{
$status = "0";
}
else
{
//Fetch all files from directory
$basepath = getcwd(); // var/app/current/example/two
$basepath = str_replace("/example/two", "", $basepath); // var/app/current
$dir = new RecursiveDirectoryIterator($basepath);
//Loop through each file
foreach(new RecursiveIteratorIterator($dir) as $files => $file)
{
if(($file->getBasename() !== ".") && ($file->getBasename() !== ".."))
{
$zip->addFile(realpath($file), $file);
}
}
$zip->close();
You should try with:
$zip->addFile(realpath($file), str_replace("/var/app/current/","",$file));
I've never used the ZipArchive class before but with most archiver application it works if you change the directory and use relative path.
So you can try to use chdir to the folder you want to zip up.
I am creating a php file that will update my site after pulling it off of BitBucket (Git repo). It downloads a zip file of the entire master or a commit, then unzips it in the website's folder.
The problem I am having is there is a randomly named folder that contains all the files in the zip file.
My zip file's contents is similar:
master.php
- (bitbucketusername)-(reponame)-(commitnumber)
- folder1
- index.php
- test.php
- index.php
- config.php
- etc...
but how can I "bypass" the "randomly" named folder and extract the contents of the folder to the website's root?
echo "Unzipping update...<br>" . PHP_EOL;
$zip = new ZipArchive;
$res = $zip->open($filename);
if ($res === TRUE) {
$zip->extractTo('/path/to/www');
$zip->close();
} else {
echo 'Error: The zip file could not be opened...<br>' . PHP_EOL;
}
Found a related question here:
Operating with zip file in PHP
But how can I make it get the "randomly" named folder's name?
Unzip the files to a tmp directory and then mv the files out from the "randomly" named parent folder to the folder that you want to.
echo "Unzipping update...<br>" . PHP_EOL;
$zip = new ZipArchive;
$res = $zip->open($filename);
if ($res === TRUE) {
$zip->extractTo('/tmp/unzip');
$directories = scandir('/tmp/unzip');
foreach($directories as $directory){
if($directory!='.' and $directory!='..' ){
if(is_dir($directory)){
// rcopy from http://ben.lobaugh.net/blog/864/php-5-recursively-move-or-copy-files
rcopy('/tmp/unzip/'.$directory,'/path/to/www');
// rm /tmp/unzip here
}
}
}
$zip->close();
} else {
echo 'Error: The zip file could not be opened...<br>' . PHP_EOL;
}
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.
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.