13,002
回編集
(ページの作成:「== 概要 == <br><br> == 圧縮 == ==== ZIP形式 ==== <syntaxhighlight lang="php"> declare(strict_types=1); namespace Utils; use RuntimeException; use ZipArchive; use Generator; /** * ZIP形式で圧縮を行うメソッド * * @param string $sourcePath 圧縮対象のパス(ファイルまたはディレクトリ) * @param string $destinationPath 出力先のZIPファイルパス * @throws RuntimeException 圧縮処理中のエラー発…」) |
(→圧縮) |
||
3行目: | 3行目: | ||
== 圧縮 == | == 圧縮 == | ||
以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。<br> | |||
また、3つの圧縮形式 (ZIP、tar.gz、tar.xz) に対応している。<br> | |||
<br> | |||
==== ZIP形式 ==== | ==== ZIP形式 ==== | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
74行目: | 77行目: | ||
try { | try { | ||
$compression->compressToZip('/path/to/source', '/path/to/output.zip'); | $compression->compressToZip('/path/to/source', '/path/to/output.zip'); | ||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== tar.gz形式 ==== | |||
<u>tar.gz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。</u><br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* tar.gz形式で圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のtar.gzファイルパス | |||
* @throws RuntimeException 圧縮処理中のエラー発生時 | |||
*/ | |||
function compressToTarGz(string $sourcePath, string $destinationPath): void | |||
{ | |||
try { | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// tarコマンドの実行 | |||
$sourceName = basename($sourcePath); | |||
$sourceDir = dirname($sourcePath); | |||
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TAR作成に失敗しました'); | |||
} | |||
// gzipでの圧縮処理 | |||
$gz = gzopen($destinationPath, 'wb9'); | |||
if ($gz === false) { | |||
throw new RuntimeException('GZIPファイルのオープンに失敗しました'); | |||
} | |||
// ストリーミング処理でTARファイルを読み込みながら圧縮 | |||
$handle = fopen($tempTarFile, 'rb'); | |||
while (!feof($handle)) { | |||
gzwrite($gz, fread($handle, 8192)); | |||
} | |||
fclose($handle); | |||
gzclose($gz); | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.gz圧縮処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド | |||
* | |||
* @param string $dir 検索対象ディレクトリ | |||
* @return Generator ファイルパスを返すジェネレータ | |||
*/ | |||
function getFilesRecursively(string $dir): Generator | |||
{ | |||
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), | |||
\RecursiveIteratorIterator::LEAVES_ONLY); | |||
foreach ($files as $file) { | |||
yield $file->getRealPath(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// tar.gz圧縮の例 | |||
$compression->compressToTarGz('/path/to/source', '/path/to/output.tar.gz'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== tar.xz形式 ==== | |||
<u>tar.xz形式の圧縮には、PHPのXZ拡張機能が必要である。</u><br> | |||
<u>また、tar.xz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。</u><br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* tar.xz形式で圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のtar.xzファイルパス | |||
* @throws RuntimeException 圧縮処理中のエラー発生時 | |||
*/ | |||
function compressToTarXz(string $sourcePath, string $destinationPath): void | |||
{ | |||
try { | |||
// PHPのXZ拡張機能が必要 | |||
if (!extension_loaded('xz')) { | |||
throw new RuntimeException('XZ拡張機能がインストールされていません'); | |||
} | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// tarコマンドの実行 | |||
$sourceName = basename($sourcePath); | |||
$sourceDir = dirname($sourcePath); | |||
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TAR作成に失敗しました'); | |||
} | |||
// XZ圧縮の実行 | |||
$xzStream = xzopen($destinationPath, 'wb9'); | |||
if ($xzStream === false) { | |||
throw new RuntimeException('XZファイルのオープンに失敗しました'); | |||
} | |||
// ストリーミング処理でTARファイルを読み込みながら圧縮 | |||
$handle = fopen($tempTarFile, 'rb'); | |||
while (!feof($handle)) { | |||
xzwrite($xzStream, fread($handle, 8192)); | |||
} | |||
fclose($handle); | |||
xzclose($xzStream); | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.xz圧縮処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド | |||
* | |||
* @param string $dir 検索対象ディレクトリ | |||
* @return Generator ファイルパスを返すジェネレータ | |||
*/ | |||
function getFilesRecursively(string $dir): Generator | |||
{ | |||
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), | |||
\RecursiveIteratorIterator::LEAVES_ONLY); | |||
foreach ($files as $file) { | |||
yield $file->getRealPath(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// tar.xz圧縮の例 | |||
$compression->compressToTarXz('/path/to/source', '/path/to/output.tar.xz'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 非同期処理 ==== | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* 非同期でファイル圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のパス | |||
* @param string $type 圧縮形式('zip', 'tar.gz', 'tar.xz'のいずれか) | |||
* @return Generator 圧縮の進捗状況を返すジェネレータ | |||
*/ | |||
function compressAsync(string $sourcePath, string $destinationPath, string $type): Generator | |||
{ | |||
yield '圧縮処理を開始します...'; | |||
try { | |||
switch ($type) { | |||
case 'zip': | |||
$this->compressToZip($sourcePath, $destinationPath); | |||
break; | |||
case 'tar.gz': | |||
$this->compressToTarGz($sourcePath, $destinationPath); | |||
break; | |||
case 'tar.xz': | |||
$this->compressToTarXz($sourcePath, $destinationPath); | |||
break; | |||
default: | |||
throw new RuntimeException('不正な圧縮形式が指定されました'); | |||
} | |||
yield '圧縮処理が完了しました'; | |||
} | |||
catch (\Exception $e) { | |||
yield "圧縮処理中にエラーが発生しました: {$e->getMessage()}"; | |||
throw $e; | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// 非同期処理の例 | |||
// ZIP形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.gz形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.xz形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
} | } | ||
catch (RuntimeException $e) { | catch (RuntimeException $e) { |