在 rsync 之后用 PHP 提取 .tar.gz

Extracting .tar.gz with PHP after rsync

我正在尝试提取一个 .tar.gz,我用 bash 在管道中压缩了它。管道使用 rsync 选择应该打包在更新中的文件,然后使用 tar:

压缩它们
rsync -azp --files-from=${RSYNC_UPDATE_FILE} --ignore-missing-args src update
tar czf ${UFILE} update

当我用像 WinRar 这样的程序打开 .tar.gz 时,文件看起来是正确的。然后我在应用程序中使用 PHP 提取更新。

# Get the full path where it should be extracted
$dirpath = $dirpath ?: File::dirname($zippath);

$phar = new \PharData($zippath);

# Check if it's compressed: e.g. tar.gz => tar
$zip = $phar->isCompressed() ? $phar->decompress() : $phar;

try {
    # Extract it to the new dir
    $extracted = $zip->extractTo($dirpath);
} catch (\Exception $e ) {
    throw new CorruptedZip("Unable to open the archive.",424,$e);
}  

提取的文件具有正确的权限、目录结构等,但我猜它们仍然是压缩的。这些文件都包含多组字符串,而不是 PHP 代码。

02a0 048b 2235 bca8 ad5e 4f7e d9be ed1f
5b00 24d5 9248 8994 2c75 f778 e293 74db
6401 a802 0af5 55e1 52fc fb37 80ff f99f

谁能看出我哪里漏掉了一步?

知道了。该错误是由于未提及的过程引起的。 Laravel 中的 UploadedFile class 将文件的 mimetype 解释为 application/x-gzip,扩展名为空,因此生成的文件被保存为 [hashed_file_name]. 而不是[hashed_file_name].tar.gz。然后(在另一台服务器上)我使用 GuzzleHttp 获取文件,并使用 Symfony 猜测扩展名。

$extension = ExtensionGuesser::getInstance()->guess($contentType);

由于 mimetype,使用 Content-Type header 获取扩展名的重建文件只是 .gz 而不是 .tar.gz.tgz .更改我的上传脚本修复了它。

$alias = $file->getClientOriginalName();
$mimetype = $file->getMimeType();
$extension = $file->guessClientExtension() ?: pathinfo($alias, PATHINFO_EXTENSION);

if ( ends_with($mimetype, 'x-gzip') && ends_with($alias, ['tar.gz', 'tgz']) ) {
    $mimetype = 'application/tar+gzip';
    $extension = 'tar.gz';
}

$hash = $file->hashName();
if ( ends_with($hash, '.') ) {
    $hash .= $extension;
}

$path = $file->storeAs($storage, $hash);