Php zip extract all

php — extract files from folder in a zip

I have a zip file containing one folder, that contains more folders and files, like this: myfile.zip
-firstlevel
—folder1
—folder2
—folder3
—file1
—file2 Now, I want to extract this file using PHPs ZipArchive, but without the «firstlevel» folder. At the moment, the results look like this: destination/firstlevel/folder1
destination/firstlevel/folder2
. The result I’d like to have would look like this: destination/folder1
destination/folder2
. I’ve tried extractTo, which produces the first mentioned result, and copy(), as suggested here, but this doesn’t seem to work at all. My current code is here:

if($zip->open('myfile.zip') === true) < $firstlevel = $zip->getNameIndex(0); for($i = 0; $i < $zip->numFiles; $i++) < $entry = $zip->getNameIndex($i); $pos = strpos($entry, $firstlevel); if ($pos !== false) < $file = substr($entry, strlen($firstlevel)); if(strlen($file) >0) < $files[] = $file; >> > //attempt 1 (extractTo): //$zip->extractTo('./test', $files); //attempt 2 (copy): foreach($files as $filename) < copy('zip://'.$firstlevel.'/'.$filename, 'test/'.$filename); >> 

What is the situation? Do the files always come in with a top level folder or do the files vary in the way they come in? How do you know that the top level will always be empty?

Exactly: The files do always come in with a top level folder, which I don’t need when extracting them on the server.

1 Answer 1

Take a look at my Quick Unzipper script. I wrote this for personal use a while back when uploading large zip files to a server. It was a backup, and 1,000s of files take forever with FTP so using a zip file was faster. I use Git and everything, but there wasn’t another option for me. I place this php file in the directory I want the files to go, and put the zip file in the same directory. For my script, they all have to operate in the same directory. It was an easy way to secure it for my needs, as everything I needed was in the same dir.

Читайте также:  Python if in list return index

I linked the file because I am not showcasing the repo, just the code that makes the unzip tick. With modern versions of PHP, there should’t be anything that isn’t included on your setup. So you shouldn’t need to do any server config changes to use this.

Here is the PHP Doc for the ZipArchive class it uses: http://php.net/manual/en/class.ziparchive.php

There isn’t any included way to do what you want, which is a shame. So I would unzip the file to a temp directory, then use another function to copy the contents to where you want. So when using ZipArchive, you will need to return the first item to get the folder name if it is unknown. If the folder is known, ie: the same pesky folder name every time, then you could hard code the name.

I have made it return the first item from the index. So if you ALWAYS have a zip with 1 folder inside it, and everything in that folder, this would work. However, if you have a zip file without everything consolidated inside 1 folder, it would fail. The code I have added will take care of your question. You will need to add further logic to handle alternate cases.

Also, You will still be left with the old directory from when we extract it to the temp directory for «processing». So I included code to delete it too.

NOTE: The code uses a lot of if’s to show the processing steps, and print a message for testing purposes. You would need to modify it to your needs.

 if ( ! is_dir($destination) && $create === true ) < @mkdir($destination); >if ( is_dir($destination) ) < $files = array_diff(scandir($source), array('.','..')); foreach ($files as $file) < if ( is_dir($file) ) < copyDirectoryContents("$source/$file", "$destination/$file"); >else < @copy("$source/$file", "$destination/$file"); >> return true; > return false; > public function removeDirectory($directory, $options=array()) < if(!isset($options['traverseSymlinks'])) $options['traverseSymlinks']=false; $files = array_diff(scandir($directory), array('.','..')); foreach ($files as $file) < if (is_dir("$directory/$file")) < if(!$options['traverseSymlinks'] && is_link(rtrim($file,DIRECTORY_SEPARATOR))) < unlink("$directory/$file"); >else < removeDirectory("$directory/$file",$options); >> else < unlink("$directory/$file"); >> return rmdir($directory); > $file = dirname(__FILE__) . '/file.zip'; // full path to zip file needing extracted $temp = dirname(__FILE__) . '/zip-temp'; // full path to temp dir to process extractions $path = dirname(__FILE__) . '/extracted'; // full path to final destination to put the files (not the folder) $firstDir = null; // holds the name of the first directory $zip = new ZipArchive; $res = $zip->open($file); if ($res === TRUE) < $firstDir = $zip->getNameIndex(0); $zip->extractTo($temp); $zip->close(); $status = "Success: '$file' extracted to '$temp'."; > else < $status = "Error: Could not extract '$file'."; > echo $status . '
'; if ( empty($firstDir) ) < echo 'Error: first directory was empty!'; >else < $firstDir = realpath($temp . '/' . $firstDir); echo "First Directory: $firstDir
"; if ( is_dir($firstDir) ) < if ( copyDirectoryContents($firstDir, $path) ) < echo 'Directory contents copied!
'; if ( removeDirectory($directory) ) < echo 'Temp directory deleted!
'; echo 'Done!
'; > else < echo 'Error deleting temp directory!
'; > > else < echo 'Error copying directory contents!
'; > > else < echo 'Error: Could not find first directory'; >>

Источник

Extract .zip files using PHP [closed]

It’s difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.

2 Answers 2

If you have zziplib installed, you can use this code:

open('test.zip') === TRUE) < $zip->extractTo('/my/destination/dir/'); $zip->close(); echo 'ok'; > else < echo 'failed'; >?> 

Make sure the user executing php (usually nobody, apache or httpd) have writing privileges on destination dir.

Use the Zip API. The algorithm for this is:

  1. Open file with zip_open
  2. Read directory entry with zip_read; if false goto step 8
  3. Get the name with zip_entry_name
  4. Open the entry with zip_entry_open
  5. Get the data with zip_entry_read, and store how & where you want
  6. Close the entry with zip_entry_close
  7. Goto step 2
  8. Close file with zip_close

I tend to steer clear of writing other people’s code for them; the focus of this site is teaching people how to solve a problem, not giving code samples for copy/paste.

It seems you misunderstood the concept of this site too much. pitty, with 5k rep, you should have known that great «teaching» is giving the example/code itself. 2×2 =4 as easy that your answer needs 20 minutes more time to spend to get the final result. p.s. you should tell 99% of users of SO to edit their answers (as they give code examples). regards and good luck.

Источник

ZipArchive::extractTo

Extract the complete archive or the given files to the specified destination.

The default permissions for extracted files and directories give the widest possible access. This can be restricted by setting the current umask, which can be changed using umask() .

Parameters

Location where to extract the files.

The entries to extract. It accepts either a single entry name or an array of names.

Return Values

Returns true on success or false on failure.

Examples

Example #1 Extract all entries

$zip = new ZipArchive ;
if ( $zip -> open ( ‘test.zip’ ) === TRUE ) $zip -> extractTo ( ‘/my/destination/dir/’ );
$zip -> close ();
echo ‘ok’ ;
> else echo ‘failed’ ;
>
?>

Example #2 Extract two entries

$zip = new ZipArchive ;
$res = $zip -> open ( ‘test_im.zip’ );
if ( $res === TRUE ) $zip -> extractTo ( ‘/my/destination/dir/’ , array( ‘pear_item.gif’ , ‘testfromfile.php’ ));
$zip -> close ();
echo ‘ok’ ;
> else echo ‘failed’ ;
>
?>

Notes

Note:

Windows NTFS file systems do not support some characters in filenames, namely <|>*?»: . Filenames with a trailing dot are not supported either. Contrary to some extraction tools, this method does not replace these characters with an underscore, but instead fails to extract such files.

User Contributed Notes 16 notes

If you want to copy one file at a time and remove the folder name that is stored in the ZIP file, so you don’t have to create directories from the ZIP itself, then use this snippet (basically collapses the ZIP file into one Folder).

$zip = new ZipArchive ;
if ( $zip -> open ( $path ) === true ) for( $i = 0 ; $i < $zip ->numFiles ; $i ++) $filename = $zip -> getNameIndex ( $i );
$fileinfo = pathinfo ( $filename );
copy ( «zip://» . $path . «#» . $filename , «/your/new/destination/» . $fileinfo [ ‘basename’ ]);
>
$zip -> close ();
>

?>

* On a side note, you can also use $_FILES[‘userfile’][‘tmp_name’] as the $path for an uploaded ZIP so you never have to move it or extract a uploaded zip file.

If you want to extract the files just to the current folder, simply use
$zip->extractTo(«.»);

It took me hours to figure this out.

The extractTo() method does not offer any parameter to allow extracting files and folders recursively from another (parent) folder inside the ZIP archive. With the following method it is possible:

class my_ZipArchive extends ZipArchive
public function extractSubdirTo ( $destination , $subdir )
$errors = array();

// Prepare dirs
$destination = str_replace (array( «/» , «\\» ), DIRECTORY_SEPARATOR , $destination );
$subdir = str_replace (array( «/» , «\\» ), «/» , $subdir );

if ( substr ( $destination , mb_strlen ( DIRECTORY_SEPARATOR , «UTF-8» ) * — 1 ) != DIRECTORY_SEPARATOR )
$destination .= DIRECTORY_SEPARATOR ;

if ( substr ( $subdir , — 1 ) != «/» )
$subdir .= «/» ;

// Extract files
for ( $i = 0 ; $i < $this ->numFiles ; $i ++)
$filename = $this -> getNameIndex ( $i );

if ( substr ( $filename , 0 , mb_strlen ( $subdir , «UTF-8» )) == $subdir )
$relativePath = substr ( $filename , mb_strlen ( $subdir , «UTF-8» ));
$relativePath = str_replace (array( «/» , «\\» ), DIRECTORY_SEPARATOR , $relativePath );

if ( mb_strlen ( $relativePath , «UTF-8» ) > 0 )
if ( substr ( $filename , — 1 ) == «/» ) // Directory
// New dir
if (! is_dir ( $destination . $relativePath ))
if (!@ mkdir ( $destination . $relativePath , 0755 , true ))
$errors [ $i ] = $filename ;
>
else
if ( dirname ( $relativePath ) != «.» )
if (! is_dir ( $destination . dirname ( $relativePath )))
// New dir (for file)
@ mkdir ( $destination . dirname ( $relativePath ), 0755 , true );
>
>

// New file
if (@ file_put_contents ( $destination . $relativePath , $this -> getFromIndex ( $i )) === false )
$errors [ $i ] = $filename ;
>
>
>
>

return $errors ;
>
>
?>

Example:
echo «» ;

$zip = new my_ZipArchive ();
if ( $zip -> open ( «test.zip» ) === TRUE )
$errors = $zip -> extractSubdirTo ( «C:/output» , «folder/subfolder/» );
$zip -> close ();

echo ‘ok, errors: ‘ . count ( $errors );
>
else
echo ‘failed’ ;
>
?>

Источник

PHP Zip: Extract contents of a directory

I need to extract the contents of a directory within a zip archive in to an output directory. The directory name inside the zip could be anything. However it will be the only directory in the base of the zip archive. There could be any number of files in the directory, in the zip archive, though. The file structure inside the zip would be along theses lines:

- d0001 - My Folder - view.php - tasks.txt - file1.txt - picture1.png - document.doc 
- My Folder - view.php - tasks.txt - file1.txt - picture1.png - document.doc 

The code I currently have deletes the contents of the output directory and extracts the entire zip archive in to the directory:

function Unzip($source, $destination) < $zip = new ZipArchive; $res = $zip->open($source); if($res === TRUE) < $zip->extractTo($destination); $zip->close(); return true; > else < return false; >> function rrmdir($dir, $removebase = true) < if(is_dir($dir)) < $objects = scandir($dir); foreach($objects as $object) < if($object != "." && $object != "..") < if(filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object); >> reset($objects); if($removebase == true) rmdir($dir); > > $filename = '/home/files.zip'; $dest = '/home/myfiles/'; if(is_dir($dest)) < rrmdir($dest, false); $unzip = Unzip($filename, $dest); if($unzip === true) < echo 'Success'; >else echo 'Extraction of zip failed.'; > else echo 'The output directory does not exist!'; 

Источник

Оцените статью