Closed andre-paulo98 closed 5 years ago
Adding intermediate directories is not require to create an archive. At the moment, directory entries are added only for directories without files.
Report what problems you are having with the file and what programs do not work with it.
$ unzip -t automatic.zip
Archive: automatic.zip
testing: data/flint_to_gravel/advancements/recipes/building_blocks/gravel.json OK
testing: data/flint_to_gravel/recipes/gravel.json OK
testing: pack.mcmeta OK
No errors detected in compressed data of automatic.zip.
$ unzip -t manual.zip
Archive: manual.zip
testing: data/ OK
testing: data/flint_to_gravel/ OK
testing: data/flint_to_gravel/advancements/ OK
testing: data/flint_to_gravel/advancements/recipes/ OK
testing: data/flint_to_gravel/advancements/recipes/building_blocks/ OK
testing: data/flint_to_gravel/advancements/recipes/building_blocks/gravel.json OK
testing: data/flint_to_gravel/recipes/ OK
testing: data/flint_to_gravel/recipes/gravel.json OK
testing: pack.mcmeta OK
No errors detected in compressed data of manual.zip.
Its some internal program that I've and for some reason this needs to have the folder structure to understand the zip correctly. I'll try to manually add the folders. I'll keep you updated
In your case, you can extend the class. I'll think about adding an option to create a folder structure.
<?php
use PhpZip\Exception\ZipException;
use PhpZip\Util\FilesUtil;
use PhpZip\ZipFileInterface;
require __DIR__ . '/vendor/autoload.php';
class CustomZipFile extends \PhpZip\ZipFile
{
/**
* Add directories from directory iterator.
*
* @param \Iterator $iterator Directory iterator.
* @param string $localPath Add files to this directory, or the root.
* @param int|null $compressionMethod Compression method.
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
* If null, then auto choosing method.
* @return ZipFileInterface
* @throws ZipException
* @see ZipFileInterface::METHOD_STORED
* @see ZipFileInterface::METHOD_DEFLATED
* @see ZipFileInterface::METHOD_BZIP2
*/
public function addFilesFromIterator(
\Iterator $iterator,
$localPath = '/',
$compressionMethod = null
)
{
$localPath = (string)$localPath;
if ($localPath !== '') {
$localPath = trim($localPath, '\\/');
} else {
$localPath = '';
}
$iterator = $iterator instanceof \RecursiveIterator ?
new \RecursiveIteratorIterator($iterator) :
new \IteratorIterator($iterator);
/**
* @var string[] $files
* @var string $path
*/
$files = [];
foreach ($iterator as $file) {
if ($file instanceof \SplFileInfo) {
if ($file->getBasename() === '..') {
continue;
}
if ($file->getBasename() === '.') {
$files[] = dirname($file->getPathname());
} else {
$files[] = $file->getPathname();
}
}
}
if (empty($files)) {
return $this;
}
natcasesort($files);
$path = array_shift($files);
foreach ($files as $file) {
$relativePath = str_replace($path, $localPath, $file);
$relativePath = ltrim($relativePath, '\\/');
if (is_dir($file)) {
$this->addEmptyDir($relativePath);
} elseif (is_file($file)) {
$this->addFile($file, $relativePath, $compressionMethod);
}
}
return $this;
}
/**
* Add files from glob pattern.
*
* @param string $inputDir Input directory
* @param string $globPattern Glob pattern.
* @param string|null $localPath Add files to this directory, or the root.
* @param bool $recursive Recursive search.
* @param int|null $compressionMethod Compression method.
* Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2.
* If null, then auto choosing method.
* @return ZipFileInterface
* @throws ZipException
* @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax
*/
private function addGlob(
$inputDir,
$globPattern,
$localPath = '/',
$recursive = true,
$compressionMethod = null
)
{
if ($inputDir === null) {
throw new InvalidArgumentException('Input dir is null');
}
$inputDir = (string)$inputDir;
if ($inputDir === '') {
throw new InvalidArgumentException('The input directory is not specified');
}
if (!is_dir($inputDir)) {
throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $inputDir));
}
$globPattern = (string)$globPattern;
if (empty($globPattern)) {
throw new InvalidArgumentException('The glob pattern is not specified');
}
$inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR;
$globPattern = $inputDir . $globPattern;
$filesFound = FilesUtil::globFileSearch($globPattern, GLOB_BRACE, $recursive);
if ($filesFound === false || empty($filesFound)) {
return $this;
}
if ($localPath !== null && is_string($localPath)) {
$localPath = trim($localPath, '/\\') . '/';
} else {
$localPath = '/';
}
/**
* @var string $file
*/
foreach ($filesFound as $file) {
$filename = str_replace($inputDir, $localPath, $file);
$filename = ltrim($filename, '\\/');
if (is_dir($file)) {
$this->addEmptyDir($filename);
} elseif (is_file($file)) {
$this->addFile($file, $filename, $compressionMethod);
}
}
return $this;
}
}
$outputFilename = 'manual.zip';
$zipFile = new CustomZipFile();
$zipFile->addDirRecursive(__DIR__ . '/manual');
$zipFile->saveAsFile($outputFilename);
$zipFile->close();
passthru('unzip -t ' . escapeshellarg($outputFilename));
Output:
Archive: manual.zip
testing: data/ OK
testing: data/flint_to_gravel/ OK
testing: data/flint_to_gravel/advancements/ OK
testing: data/flint_to_gravel/advancements/recipes/ OK
testing: data/flint_to_gravel/advancements/recipes/building_blocks/ OK
testing: data/flint_to_gravel/advancements/recipes/building_blocks/gravel.json OK
testing: data/flint_to_gravel/recipes/ OK
testing: data/flint_to_gravel/recipes/gravel.json OK
testing: pack.mcmeta OK
No errors detected in compressed data of manual.zip.
Using the class you made it does create the structure and the program can indeed read it. Appreciate your help!
Description
For some reason, the zip that this library creates its not recognized in some programs, did a zipinfo on the zip that was generated and this was the output: Then on my computer I unziped it and zip it back (with 7zip manually) and this was the output:
How to reproduce
I've tried $zip->addDirRecursive() and $zip->addFilesFromIterator() and got the same result on both cases.
Additional context
The zips that were used: manual.zip automatic.zip