Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active May 9, 2019 05:40
Show Gist options
  • Save yano3nora/881ac7789602fe2fc5c48d20ea838300 to your computer and use it in GitHub Desktop.
Save yano3nora/881ac7789602fe2fc5c48d20ea838300 to your computer and use it in GitHub Desktop.
[php: zipArchive] zipArchive - php zip handler class. #php

Overview

ZipArchive - php.net

PHP で ZIP をこねる用の標準ライブラリ。利用には PHP 5.2 以上かつ php.ini にて拡張設定 ( extension=zip.so ) が必要。パスワード ZIP の解凍は問題ないが、パスワード付 ZIP の作成には PHP 7.2 以上が必要っぽい。

Zip

$files   = array('file1.txt', 'file2.txt');
$zip     = new ZipArchive();
$zipName = 'hoge.zip';
$zipPath = '/var/www/app/tmp/'.$zipName;
$res     = $zip->open($zipPath, ZipArchive::CREATE);
if ($res === true) {
  foreach($files as $file){
    $zip->addFile($file);
  }
  $zip->close();
} else {
  echo 'Error Code: ' . $res;
}

Encrypted zip

To create password protected archive in PHP >= 7.2 use - php.net
ZipArchive::setEncryptionName() - php.net
Creating encrypted ZIP files with password in PHP

$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) {
    $zip->setPassword('secret');
    $zip->addFile('text.txt');
    $zip->setEncryptionName('text.txt', ZipArchive::EM_AES_256);
    $zip->close();
    echo "Ok\n";
} else {
    echo "KO\n";
}

Unzip

$file = './test.zip';
$to = './test/';
$zip = new ZipArchive();
$res = $zip->open($file);
if ($res === true) {
  $zip->extractTo($to);
  $zip->close();
} else {
  echo 'Error Code: ' . $res;
}

List

$zip_path = "D:\data.zip";
$zip = new ZipArchive();
$res = $zip->open($zip_path);
for ($i=0; $i<$zip->numFiles; $i++) {
    echo 'エントリ名 : ' . $zip->getNameIndex($i) . '\n';
}
// 出力結果
// ---------------------------------
// エントリ名 : data/file1.xls
// エントリ名 : data/file2.txt
// エントリ名 : data/subdir/
// エントリ名 : data/subdir/file1.xls
// エントリ名 : data/subdir/file2.txt

TIPS

ファイル名が日本語だと解答時に無視されちゃう

ZipArchiveのextractToで日本語ファイルが解凍できない

setlocale(LC_ALL, 'ja_JP.UTF-8');  // 無理やり locale 設定
$ZipHandler->extractTo(FILES_DIR.DS);
$ZipHandler->close();

ZIP 内の日本語ファイル名の文字コードが UTF-8 と自動判定され壊れる

PHP7でZipArchiveを使うと日本語ファイル名が化ける問題

// 読み取り時は文字コード変更しとく
$ZipHandler = new \ZipArchive();
if (!$ZipHandler->open($zipPath, \ZipArchive::CREATE)) throw new \Exception('ZIP ファイルの読み取りに失敗しました。');
for ( $i = 0; $i < $ZipHandler->numFiles; $i++ ) {
  $fileStat = $ZipHandler->statIndex($i, \ZipArchive::FL_ENC_RAW);  // ZipArchive::FL_ENC_RAW で自動判定を抑止
  $fileName = mb_convert_encoding($fileStat['name'], 'UTF-8', 'auto');
  $ZipHandler->renameIndex($i, $fileName);
}

// SJIS なやつを ZIP する書き込み時は普通に mb_convert_encoding しとけば OK
$name = mb_convert_encoding($name, 'SJIS-win', 'UTF-8');
$zip->addFromString($name, $content);

解凍後のフォルダ名が知りたい

$extractedDirName = substr(trim($zipHandler->getNameIndex(0)), 0, strcspn($zipHandler->getNameIndex(0), DS));

zipファイル名と元のディレクトリ名が違うときのだるいやつ

// getNameIndexで各ファイル名をとり
// renameIndex で 都合のよい状態にリネーム
$zipHandler = new ZipArchive(); 
$zipHandler->open($zipPath, ZipArchive::CREATE)) {
for ( $i = 0; $i < $zipHandler->numFiles; $i++ ) {
  $zipHandler->renameIndex($i, basename($zipHandler->getNameIndex($i)));
  $images[] = $zipHandler->getNameIndex($i);
}
mkdir($dirName);
$zipHandler->extractTo($dirName.DS, $images);
$zipHandler->close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment