Unzip file skipping folder - php

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;
}

Related

Php Ziparchive extractTo method not extracting zip files

I'm trying to extract a directory of zip files in the same directory they are located in.
public function buildRecords($quickCheckOutputDir, $salvageVinsDir)
{
//unzip
$files_to_extract = $this->getFiles($salvageVinsDir);
$zip = new ZipArchive();
foreach($files_to_extract as $file) {
$res = $zip->open($salvageVinsDir . $file);
if($res) {
echo $zip->extractTo($salvageVinsDir);
//$zip->deleteName($salvageVinsDir . $file);
$zip->close();
} else {
echo 'failed, code:' . $res;
}
}
}
The echo $zip->extractTo($salvageVinsDir) returns 1 so I would think that the method is working but when I check the directory only the zipped files are there. Nothing has been extracted. What is the issue here?
Edit: I gave the directory I'm working in chmod 777.I'm working on centos 7.

Archive a .wdgt folder in ZipArchive()

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.

Zip/Unzip with php

I am doing a backup module, I need to zip all the webapp folder, I use this method:
function agregar_zip($dir, $zip){
if (is_dir($dir)) {
if ($da = opendir($dir)) {
while (($archivo = readdir($da))!== false) {
if (is_dir($dir . $archivo) && $archivo!="." && $archivo!=".."){
agregar_zip($dir.$archivo . "/", $zip);
}elseif(is_file($dir.$archivo) && $archivo!="." && $archivo!=".."){
$zip->addFile($dir.$archivo, $dir.$archivo);
}
}
closedir($da);
}
}
}
$zip = new ZipArchive();
$dir = Yii::app()->basePath.'/../';
$rutaFinal="c:/xampp/htdocs/";
$archivoZip = "backup.zip";
if($zip->open($archivoZip,ZIPARCHIVE::CREATE)===true) {
agregar_zip($dir, $zip);
$zip->close();
#rename($archivoZip, "c:/xampp/htdocs/backup.zip");
if (file_exists($rutaFinal.$archivoZip)){
}else{
Yii::app()->params['errores'] = Yii::app()->params['errores']."</br>No se ha creado el ZIP con éxito.";
}
}
When I open the file.zip, I have this structure:
C:/->xampp->htdocs->mywebapp(Here is all I need)
But If I do "extract here" Its unzip the right content, but If I do with php it create a folder in destination called xampp, inside it htdocs, inside it mywebapp(With the right content).
I need to zip only the app folder not all the route. This way when I unzip with php only unzip app folder.
I think you need to remove the "/../" from this line
$dir = Yii::app()->basePath.'/../';
should be
$dir = Yii::app()->basePath;
There is better way to make zip with yii.
Yii has a zip extension.
Usage example from the docs above:
Introduce EZip to Yii. Add definition to CWebApplication config file (main.php)
'components'=>array(
...
'zip'=>array(
'class'=>'application.extensions.zip.EZip',
),
...
),
Now you can access EZip methods as follows:
$zip = Yii::app()->zip;
$zip->makeZip('./','./toto.zip'); // make an ZIP archive
var_export($zip->infosZip('./toto.zip'), false); // get infos of this ZIP archive (without files content)
var_export($zip->infosZip('./toto.zip')); // get infos of this ZIP archive (with files content)
$zip->extractZip('./toto.zip', './1/'); //

How to achieve the following file structure when archiving a directory in PHP using ZipArchive();

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.

ZipArchive .zip file to show all files in root

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");
}

Categories