When working with ZIP files in PHP, the zip_read() function helps us read the contents of the compressed files one by one. By combining it with the scandir() function for recursive folder operations, we can easily implement an automatic ZIP extraction function that preserves its directory structure on the server. This article will explain in detail how to build such a script using these two functions.
Ensure that the zip extension is enabled in your PHP environment. If not, you can enable it by editing your php.ini file and uncommenting the following line:
extension=zip
Then, restart your web server.
Open the ZIP file;
Iterate through each entry in the ZIP;
Check if the entry is a directory or a file;
Use scandir() in combination with a custom function to recursively create the directory structure;
Write the files from the ZIP to the target path.
<?php
<p>function createDirRecursive($path) {<br>
if (!is_dir($path)) {<br>
mkdir($path, 0777, true);<br>
}<br>
}</p>
<p>function unzipWithStructure($zipFilePath, $destination) {<br>
$zip = zip_open($zipFilePath);</p>
while ($zip_entry = zip_read($zip)) {
$entryName = zip_entry_name($zip_entry);
$fullPath = $destination . '/' . $entryName;
// Create the directory if it's a directory
if (substr($entryName, -1) === '/') {
createDirRecursive($fullPath);
} else {
// Ensure the directory for the file exists
$dirPath = dirname($fullPath);
createDirRecursive($dirPath);
if (zip_entry_open($zip, $zip_entry)) {
$fileContent = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
file_put_contents($fullPath, $fileContent);
zip_entry_close($zip_entry);
}
}
}
zip_close($zip);
} else {
echo "Unable to open ZIP file: $zipFilePath";
}
}
// Example usage
$zipPath = '/var/www/html/uploads/sample.zip';
$extractTo = '/var/www/html/extracted';
// Call the function to unzip
unzipWithStructure($zipPath, $extractTo);
?>
You can further verify that the target directory structure has been correctly created using scandir(). For example:
function listAllFiles($dir) {
$files = scandir($dir);
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
$path = $dir . '/' . $file;
if (is_dir($path)) {
echo "Directory: $path\n";
listAllFiles($path);
} else {
echo "File: $path\n";
}
}
}
<p>listAllFiles('/var/www/html/extracted');<br>
After executing the above code, it will output all the extracted files and folders, which is useful for debugging and verification.
Use absolute paths for all paths to avoid permission or path errors;
In a production environment, ensure the source of the ZIP file is safe to prevent directory traversal attacks (for example, ZIP files containing ../../);
You can normalize paths using realpath();
If the files are large, it's recommended to handle them using streaming to prevent memory overflow.
This script is suitable for automatically extracting ZIP files uploaded by users. For example, if a user uploads a ZIP file with a multi-layer directory structure to m66.net/upload, the backend can directly use the above script to restore the full structure in the m66.net/storage directory, and further process the content, such as generating thumbnails, scanning for viruses, or backing up the data.
By doing this, the content upload and file initialization process can be greatly simplified, improving development efficiency.