How to work with archives in PHP
Archive opening example:
Archive files iterating example (without extracting):
Archive extracting & recursive files iterating (via RecursiveIteratorIterator and RecursiveDirectoryIterator) example:
And make sure that after any actions with extracted files you will delete temporary directory with the extracted archive. I suggest doing this in finally construction in case there is any error during your code work:
<?php
...
$zip = new ZipArchive();
$archivePath = $archive->getPathname();
if (true !== $zip->open($archivePath)) {
throw new \RuntimeException(sprintf('Cannot open archive "%s".', $archivePath));
}
...
Archive files iterating example (without extracting):
<?php
...
/** @var ZipArchive $zip */
for ($i = 0; $i < $zip->numFiles; ++$i) {
$fileName = $zip->getNameIndex($i);
$stream = $zip->getStream($fileName);
if ($stream) {
$content = stream_get_contents($stream);
// do something with content
// if content is text - you can easily work with them!
fclose($stream);
}
}
...
Archive extracting & recursive files iterating (via RecursiveIteratorIterator and RecursiveDirectoryIterator) example:
<?php
...
// extraction
$tempDir = sys_get_temp_dir() . sprintf('/%s', 'archive_') . uniqid('', true);
if (false === @mkdir($tempDir, 0777, true) && !is_dir($tempDir)) {
throw new RuntimeException(sprintf('Unable to create the "%s" directory.', $tempDir));
}
$zip->extractTo($tempDir);
$zip->close();
// iteration
/** @var \SplFileInfo $file */
foreach ($filesFirstIterator as $file) {
$pathName = $file->getPathname();
if ($file->isDir()) {
// do something
}
if($file->isFile()) {
// do domething
}
}
And make sure that after any actions with extracted files you will delete temporary directory with the extracted archive. I suggest doing this in finally construction in case there is any error during your code work:
<?php
...
public function uploadArchiveAction(Request $request): Response
{
try {
// your logic
} catch (\Throwable $exception) {
// do any actions
} finally {
$this->deleteDirectory($tempDir);
}
}
private function deleteDirectory(string $dir): void
{
if (!is_dir($dir)) {
return;
}
$filesFirst = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($filesFirst as $file) {
$pathName = $file->getPathname();
if ($file->isDir()) {
rmdir($pathName);
} else {
unlink($pathName);
}
}
rmdir($dir);
}
5 месяцев назад