php RAR压缩

2021-03-18
/**
 * @description: RAR读取,不支持创建
 *               扩展安装地址:https://pecl.php.net/package/rar
 */
class RARCompress
{
    /**
     * @description: rar文件资源
     * @var RarArchive
     */
    protected $rar;

    public function __construct($filename, $password = null)
    {
        // 发生错误时抛出异常而不是发出警告
        RarException::setUsingExceptions(true);
        $this->getRar($filename, $password);
    }

    public function __destruct()
    {
        $this->rar->close();
    }

    /**
     * @description: 获取rar资源
     * @param string $filename 文件路径
     * @param string $password 文件密码
     * @return {*}
     */
    public function getRar($filename, $password = null)
    {
        $this->rar = RarArchive::open(realpath($filename), $password);
        if ($this->rar) {
            if ($this->rar->isBroken()) {
                throw new \Exception('文件不完整(卷丢失或被截断)');
            }
        } else {
            throw new \Exception('压缩包错误');
        }
    }

    /**
     * @description: 获取压缩包中指定路径的条目对象
     * @param string $path 压缩包中的路径
     * @return {*}
     */
    public function getOne($path)
    {
        try {
            $entry = $this->rar->getEntry($path);
            return $this->entryAttribute($entry);
        } catch (RarException $e) {
            throw new \Exception('条目不存在');
        }
    }

    /**
     * @description: 解压缩文件,压缩包中的多层目录会自动处理
     * @param string $dir 解压缩路径,默认当前目录;绝对路径相对路径都可以,
     *                      路径中的目录不存在时将自动创建,路径中不要带中文
     *                      压缩包中的中文不会乱码
     * @return {*}
     */
    public function uncompress($dir = '')
    {
        // 获取压缩包中所有条目对象
        foreach($this->rar->getEntries() as $entry) {
            // 解压到指定目录,true表示设置诸如NTFS ACL和Unix所有者信息之类的扩展信息,只要它们存在
            $entry->extract($dir, '', null, true);
        }
    }

    /**
     * @description: 压缩条目属性
     * @param RarEntry $entry 压缩条目
     * @return {*}
     */
    protected function entryAttribute($entry)
    {
        $is_dir = (bool)(
            // 获取存档条目的主机操作系统的代码             获取档案条目的OS相关属性
            ((($entry->getHostOs() == RAR_HOST_WIN32) && ($entry->getAttr() & 0x10)) ||  // 支持Windows
            (($entry->getHostOs() == RAR_HOST_UNIX) && (($entry->getAttr() & 0xf000) == 0x4000))) // 支持Unix
        );
        $name  = $entry->getName();
        if ($is_dir && $entry->isDirectory()) {
            $dir  = $name;
            $file = '';
        } else {
            $names = explode('\\', $name);
            $file  = array_pop($names);
            $dir   = $names ? implode('/', $names) : '/';
        }

        return [
            'is_dir'        => $is_dir,
            'dir'           => $dir,
            'name'          => $file,
            'packed_size'   => $entry->getPackedSize(), // 压缩大小
            'unpacked_size' => $entry->getUnpackedSize(), // 解压缩后的大小
            'last_time'     => $entry->getFileTime(), // 文件最后修改时间
        ];

    }

    /**
     * @description: 异常转换
     * @param int $code 异常编码
     * @return {*}
     */
    protected function exceptionCode($code)
    {
        return [
            -1 => 'UnRAR 库之外的错误',
            11 => '内存不足',
            12 => '错误数据',
            13 => '存档错误',
            14 => '未知格式',
            15 => '文件打开错误',
            16 => '文件创建错误',
            17 => '文件关闭错误',
            18 => '读取错误',
            19 => '写入错误',
            20 => '缓冲区太小',
            21 => '未知的 RAR 错误',
            22 => '需要密码但未提供'
        ][$code] ?? '';
    }
}

 

{/if}