PHP Untar-gz 不带 exec() 吗?

问题描述 投票:0回答:3

如何使用纯 PHP 在不使用

exec('tar')
或任何其他命令的情况下解压 php 中的文件?

我的问题如下;我有一个 26mb tar.gz 文件,需要将其上传到我的服务器上并解压。我尝试过使用net2ftp来解压,但它不支持tar.gz上传后解压。

我正在使用免费的网络主机,因此他们不允许任何

exec()
命令,并且不允许访问提示。那么我该如何解压这个呢?

PHP 有内置命令吗?

php exec tar
3个回答
55
投票

从 PHP 5.3.0 开始,您不需要使用

Archive_Tar

有新的类可以处理 tar 存档:PharData 类

要提取存档(使用

PharData::extractTo()
,其工作方式类似于
ZipArchive::extractTo()
):

try {
    $phar = new PharData('myphar.tar');
    $phar->extractTo('/full/path'); // extract all files
} catch (Exception $e) {
    // handle errors
}

如果您有 tar.gz 存档,只需在提取之前将其解压(使用

PharData::decompress()
):

// decompress from gz
$p = new PharData('/path/to/my.tar.gz');
$p->decompress(); // creates /path/to/my.tar

// unarchive from the tar
$phar = new PharData('/path/to/my.tar');
$phar->extractTo('/full/path');

3
投票

PEAR 提供了

Archive_Tar
,它支持 Gzip 和 BZ2 压缩,前提是您分别加载了 zlib 和 bz2 扩展。


0
投票

我写了一个PHP函数,可以在没有Phar的情况下使用。 它还适用于长文件名,并使用大型 TAR 存档进行了测试。与 PHP 5 至 8 兼容。

用途:

<?php

$ret = tar_extract ("filename.tar", "./path-to-extract/");

if (empty ($ret["errText"])) {
    print ($ret["fileCnt"]." files extracted.");
    print ($ret["log"]);
}
else {
    print ("Error: ".$ret["errText"]);
    print ($ret["log"]);
}

?>

TAR 存档功能:

<?php

function tar_truncate_name (&$str) {
    for ($i=0;$i<strlen ($str);$i++) {
        if (0==ord (substr ($str, $i, 1)))
            break;
    }
    $str = substr ($str, 0, $i);
}

function tar_checksum (&$str, $size) {
    $checksum = 0;
    for ($i=0;$i<$size;$i++) {
        $checksum += ord (substr ($str, $i, 1));
    }
    return $checksum;
}

function tar_read_header ($fh) {
    $header = array (
    "name"    => 100,
    "mode"    => 8,
    "uid"     => 8,
    "gid"     => 8,
    "size"    => 12,
    "mtime"   => 12,
    "chksum"  => 8,
    "linkflag"=> 1,
    "linkname"=> 100,
    "magic"   => 8,
    "uname"   => 32,
    "gname"   => 32,
    "devmajor"=> 8,
    "devminor"=> 8,
    "rest"    => 167
    );

    $dataPos = ftell ($fh)+512;
    $stat = fstat($fh);
    $filesize = $stat['size'];
    if ($dataPos>$filesize) {
        return -1;
    }

    $checksum = 0;
    foreach ($header as $key => $len) {    
        $header[$key] = fread ($fh, $len);
        $read = strlen ($header[$key]);
        if ($read<$len) 
            return -1;
        if ($key=="chksum") {
            $empty = "        ";
            $checksum+=tar_checksum ($empty, 8);
        }
        else {
            $checksum+=tar_checksum ($header[$key], $len);
        }
    }
    
    tar_truncate_name ($header["chksum"]);
    if (empty ($header["chksum"])) {
        return false; // Last TAR header
    }

    // Check checksum   
    if ($header["chksum"]!=sprintf ("%06o", $checksum)) {
        print_r ($header);
        return -1;
    }

    // Convert form octal to decimal
    if (sscanf ($header["size"], "%o", $header["size"])!=1)
        return false;

    if (sscanf ($header["mtime"], "%o", $header["mtime"])!=1)
        return false;

    // Truncate names
    tar_truncate_name ($header["name"]);
    tar_truncate_name ($header["linkname"]);
    tar_truncate_name ($header["uname"]);
    tar_truncate_name ($header["gname"]);

    fseek ($fh, $dataPos);

    if ($header["linkflag"]=="L" && $header["name"]=="././@LongLink") {
        // Read long filename       
        $longFilename = fread ($fh, $header["size"]);
        if (strlen ($longFilename)!=$header["size"])
            return -1;
            // Skip 512 Byte block
            if ($header["size"]<512)
                $size=512-$header["size"];
            else
            $size=(512-($header["size"] % 512));
            fseek ($fh, ftell ($fh)+$size);
            // Now comes the real block
            $header = tar_read_header ($fh);
            if (!is_array ($header)) {
                return -1;
        }
        else {
            $header["name"]=trim ($longFilename);
        }
    }

    // Remove relative paths for security
    $header["name"] = str_replace (["../", "..\\"], ["./", "./"], $header["name"]);

    return $header;
}

function tar_extract ($tarFilename, $dstPath=".") {

    $ret = array (
        "fileCnt" => 0,
        "dirCnt" => 0,
        "size" => 0,
        "log" => "",
        "errText" => ""
    );

    $fh = fopen ($tarFilename, "r");

    if (!$fh) {
        $ret["errText"] = "Cannot open TAR file: ".$tarFilename;
        $ret["log"].=$ret["errText"]."\r\n";
        return $ret;
    }

    while (!feof ($fh)) {
        $header = tar_read_header ($fh);
        if (!is_array ($header)) {
            if ($header==-1) {
                $ret["errText"] = "TAR header corrupt.";
                $ret["log"].=$ret["errText"]."\r\n";
            }
            break;
        }
        else
        if ($header["linkflag"]==0) {
            $ret["log"].=$header["name"].", ".$header["size"]."\r\n";
            // Read file
            $dstFilename = $dstPath."/".$header["name"];
            $fh2 = fopen ($dstFilename, "w+");
            if (!$fh2) {
                $ret["errText"] = "Cannot create file: ".$dstFilename;
                $ret["log"].=$ret["errText"]."\r\n";
                break;
            }
            else {
                $size = $header["size"];
                $buf = "";
                while ($size>0) {
                    $bufSize = 0xFFFF;
                    if ($size<$bufSize)
                        $bufSize=$size;
                    $buf = fread ($fh, $bufSize);
                    $read = strlen ($buf);
                    if ($read<=0)
                        break;
                    fwrite ($fh2, $buf);
                    $size-=$read;
                }
                fclose ($fh2);
                // Set file time
                touch ($dstFilename, $header["mtime"], $header["mtime"]);
                if ($size>0) {
                    $ret["errText"] = "Filesize incorrect: ".$dstFilename;
                    $ret["log"].=ret["errText"]."\r\n";
                    break;
                }
            }
            // Skip 512 Byte block
            if (($header["size"]%512)!=0) {
                if ($header["size"]<512)
                    $rest = 512-$header["size"];
                else
                    $rest = 512-($header["size"] % 512);
                fseek ($fh, ftell ($fh)+$rest);
            }
            $ret["fileCnt"]++;
            $ret["size"]+=$header["size"];
        }
        else 
        if ($header["linkflag"]==5) {
            if (!is_dir ($dstPath."/".$header["name"])) {
                if (!mkdir ($dstPath."/".$header["name"])) {
                    $ret["errText"] = "Cannot create directory: ".$dstPath."/".$header["name"];
                    $ret["log"].=$ret["errText"]."\r\n";
                    break;
                }
            }
            $ret["dirCnt"]++;
            // Set directory time
            touch ($dstPath."/".$header["name"], $header["mtime"], $header["mtime"]);
        }
        else {
            // Unknown linkflag
            // Ignore header but skip size
            if ($header["size"]>0) {
                $size = $header["size"];
                // Skip 512 Byte block
                if ($header["size"]<512)
                  $size=512;
                else
                    $size+=(512-($header["size"] % 512));
                fseek ($fh, ftell ($fh)+$size);
            }
        }
    }
    fclose ($fh);
    return $ret;
}

?>
© www.soinside.com 2019 - 2024. All rights reserved.