Extract specific files to zip (including subdirectories)

I want to extract only images from a zip file, but also want it to also extract images found in subfolders. How can this be done based on my code below. Note: I am not trying to maintain the directory structure here; I just want to extract any image found in zip.

//extract files in zip for ($i = 0; $i < $zip->numFiles; $i++) { $file_name = $zip->getNameIndex($i); $file_info = pathinfo($file_name); //if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve if (in_array($file_info['extension'], $this->config->getValidExtensions())) { //extract only images copy("zip://" . $zip_path . "#" . $file_name, $this->tmp_dir . '/images/' . $file_info['basename']); } } $zip->close(); 

Edit

My code works fine and I need to know how to make ziparchive also in subdirectories

+5
source share
4 answers

Your code is correct. I created a.zip with a/b/c.png , d.png :

 $ mkdir -pa/b $ zip -r a.zip d.png a adding: d.png (deflated 4%) adding: a/ (stored 0%) adding: a/b/ (stored 0%) adding: a/b/c.png (deflated 8%) $ unzip -l a.zip Archive: a.zip Length Date Time Name --------- ---------- ----- ---- 122280 11-05-2016 14:45 d.png 0 11-05-2016 14:44 a/ 0 11-05-2016 14:44 a/b/ 36512 11-05-2016 14:44 a/b/c.png --------- ------- 158792 4 files 

The code extracted both d.png and c.png from a.zip into the target directory:

 $arch_filename = 'a.zip'; $dest_dir = './dest'; if (!is_dir($dest_dir)) { if (!mkdir($dest_dir, 0755, true)) die("failed to make directory $dest_dir\n"); } $zip = new ZipArchive; if (!$zip->open($arch_filename)) die("failed to open $arch_filename"); for ($i = 0; $i < $zip->numFiles; ++$i) { $path = $zip->getNameIndex($i); $ext = pathinfo($path, PATHINFO_EXTENSION); if (!preg_match('/(?:jpg|png)/i', $ext)) continue; $dest_basename = pathinfo($path, PATHINFO_BASENAME); echo $path, PHP_EOL; copy("zip://{$arch_filename}#{$path}", "$dest_dir/{$dest_basename}"); } $zip->close(); 

Testing

 $ PHP .php d.png a/b/c.png $ find ./dest -type f ./dest/d.png ./dest/c.png 

So the code is correct, and the problem should be somewhere else.

+1
source

Based on the file extension (not necessarily the most reliable method) you can find the following message.

 /* source zip file and target location for extracted files */ $file='c:/temp2/experimental.zip'; $destination='c:/temp2/extracted/'; /* Image file extensions to allow */ $exts=array('jpg','jpeg','png','gif','JPG','JPEG','PNG','GIF'); $files=array(); /* create the ZipArchive object */ $zip = new ZipArchive(); $status = $zip->open( $file, ZIPARCHIVE::FL_COMPRESSED ); if( $status ){ /* how many files are in the archive */ $count = $zip->numFiles; for( $i=0; $i < $count; $i++ ){ try{ $name = $zip->getNameIndex( $i ); $ext = pathinfo( $name, PATHINFO_EXTENSION ); $basename = pathinfo( $name, PATHINFO_BASENAME ); /* store a reference to the file name for extraction or copy */ if( in_array( $ext, $exts ) ) { $files[]=$name; /* To extract files and ignore directory structure */ $res = copy( 'zip://'.$file.'#'.$name, $destination . $basename ); echo ( $res ? 'Copied: '.$basename : 'unable to copy '.$basename ) . '<br />'; } }catch( Exception $e ){ echo $e->getMessage(); continue; } } /* To extract files, with original directory structure, uncomment below */ if( !empty( $files ) ){ #$zip->extractTo( $destination, $files ); } $zip->close(); } else { echo $zip->getStatusString(); } 
0
source

This will allow you to navigate all the directories in the path and will look for everything that the image has / has the extensions that you defined. Since you told the other user that you have a ziparchive part, I omitted this ...

 <?php function traverse($path, $images = []) { $files = array_diff(scandir($path), ['.', '..']); foreach ($files as $file) { // check if the file is an image if (in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['jpg', 'jpeg', 'png', 'gif'])) { $images[] = $file; } if (is_dir($path . '/' . $file)) { $images = traverse($path . '/' . $file, $images); } } return $images; } $images = traverse('/Users/kyle/Downloads'); 

You want to complete this process:

  • Get all files in the current working directory
  • If the file in CWD is an image, add it to the image array
  • If the file in CWD is a directory, the trace function is recursively called and looks for images in the directory
  • In the new CWD, find the images if the file is a directory registry, etc.

It is important to keep track of the current path so that you can call is_dir in the file. Also you want not to search for "." or "..", or you will never come across a basic recursive case / it will be infinite.

Also, this will not support the directory path for the image! If you want to do this, you must do $image[] = $path . '/' . $file; $image[] = $path . '/' . $file; . You might want to do this, and then get the entire contents of the file so that the function exits. I would not recommend sorting the contents in the $ image array, because it could use an absurd amount of memory.

0
source

First of all, to keep track of a folder, take this into account - your code does not.

There are no folders in the ZIP archive (in fact, even in the file system the β€œfolder” is a file, just a special one). The file (data) has a name, possibly contains a path (most likely, relative). If "go in subdiectorsies" means that you need the same relative folder structure of zipped files in your file system, you must write code to create these folders. I think the copy will not do this automatically.

I changed your code and added folder creation. Pay attention to the configuration variables that I had to add in order to make it workable, configure it in your environment. I also left all my debug output. The code works autonomously for me in Windows 7, PHP 5.6

 error_reporting(-1 ); ini_set('display_errors', 1); $zip_path = './test/cgiwsour.zip'; $write_dir = './test'; // base path for output $zip = new ZipArchive(); if (!$zip->open($zip_path)) die('could not open zip file '.PHP_EOL); $valid_extensions = ['cpp']; $create_subfolders = true; //extract files in zip for ($i = 0; $i < $zip->numFiles; $i++) { $file_name = $zip->getNameIndex($i);var_dump($file_name, $i); $file_info = pathinfo($file_name);//print_r($file_info); //if ( substr( $file_name, -1 ) == '/' ) continue; // skip directories - need to improve if (isset($file_info['extension']) && in_array(strtolower($file_info['extension']), $valid_extensions)) { $tmp_dir = $write_dir; if ($create_subfolders) { $dir_parts = explode('/', $file_info['dirname']); print_r($dir_parts); foreach($dir_parts as $folder) { $tmp_dir = $tmp_dir . '/' . $folder; var_dump($tmp_dir); if (!file_exists($tmp_dir)) { $res = mkdir($tmp_dir); var_dump($res); echo 'created '.$tmp_dir.PHP_EOL; } } } else { $tmp_dir .= '/' . $file_info['dirname']; } //extract only images $res = copy("zip://" . $zip_path . "#" . $file_name, $tmp_dir . '/' . $file_info['basename']); echo 'match : '.$file_name.PHP_EOL; var_dump($res); } } $zip->close(); 

It is noticeable that calls to mkdir () may work flawlessly on all systems due to access / rights restrictions.

0
source

Source: https://habr.com/ru/post/1259137/


All Articles