Ne-Lexa / php-zip

PhpZip is a php-library for extended work with ZIP-archives.
MIT License
491 stars 60 forks source link

How fix Warning: touch(): Utime failed: Operation not permitted in /var/www/vendor/nelexa/zip/src/ZipFile.php on line 540 #62

Closed 4ubi closed 4 years ago

4ubi commented 4 years ago

PHP Warning: touch(): Utime failed: Operation not permitted in /var/www/vendor/nelexa/zip/src/ZipFile.php on line 540 PHP Stack trace: PHP 1. {main}() /var/www/bin/console:0 PHP 2. Symfony\Component\Console\Application->run() /var/www/bin/console:46 PHP 3. Symfony\Component\Console\Application->doRun() /var/www/vendor/symfony/console/Application.php:145 PHP 4. Symfony\Component\Console\Application->doRunCommand() /var/www/vendor/symfony/console/Application.php:269 ..... PHP 10. PhpZip\ZipFile->extractTo() /var/www/src/Command/AbstractAmplitudeTransferCommand.php:234 PHP 11. touch() /var/www/vendor/nelexa/zip/src/ZipFile.php:540

Ne-Lexa commented 4 years ago

Sounds like a file permissions issue. Make sure the owner and permissions are correct.

Ne-Lexa commented 4 years ago

Please show your PHP code that caused the error.

4ubi commented 4 years ago

private function extractDataFromZip(StreamInterface $bodyResponse) { try { $this->zipFile->openFromString($bodyResponse);

        if (!$this->zipFile->valid()) {
            return;
        }

        $this->zipFile->extractTo(self::UNZIP_DIR);

        $listFiles = $this->zipFile->getListFiles();

        $tempDir = stristr($listFiles[0], '/', true);

        $this->zipFile->close();

        foreach ($listFiles as $gzipFile) {
            yield gzfile(self::UNZIP_DIR . $gzipFile);

            unlink(self::UNZIP_DIR . $gzipFile);
        }

        exec("rm -rf " . self::UNZIP_DIR . $tempDir);
    } catch (Exception $exception) {
        $this->zipFile->close();
        throw $exception;
    }
}
Ne-Lexa commented 4 years ago
  1. $this->zipFile->valid() The valid method is not for validation, but for iteration.
  2. $this->zipFile->extractTo(self::UNZIP_DIR); the method can return a list of extracted files:
        $zipFile->extractTo(self::UNZIP_DIR, null, [], $extractedEntries);
        $zipFile->close();

        foreach ($extractedEntries as $fileName => $zipEntry){
            yield gzfile($fileName); // what is it?!
            unlink($fileName);
        }
  1. You do not need to extract the zip, you can read it directly, including as a stream.
  2. Show the process of creating the self :: UNZIP_DIR directory and what permissions it has.
4ubi commented 4 years ago
  1. UNZIP_DIR = '/var/www/log'. premissions set chmod 777.
  2. yield gzfile($fileName) - the zip archive contains gzip archives, I need to extract data from gzip archives (this is how the api Amplitudes works), for this I extract data from the zip archive and then iteratively read the data through the list of files
Ne-Lexa commented 4 years ago

Please attach an example zip file that is causing the problem. I will try to help you.

4ubi commented 4 years ago

I figured it out! Thanks a lot for the explanation, item 2 from the post above opened my eyes and I solved my problem.

Ne-Lexa commented 4 years ago

Possible problem with file permissions due to the fact that the files have chmod 0600 in the zip archive and when unpacked it is also installed. image I don't know the exact reasons yet, I can't reproduce this error.

I propose to rewrite the version without unzipping the archive.

<?php

require_once __DIR__.'/vendor/autoload.php';

function extractDataFromZip(string $zipContents)
{
    $zipFile = new \PhpZip\ZipFile();
    try {
        $zipFile->openFromString($zipContents);
        foreach ($zipFile as $entryName => $contents) {
            yield $entryName => gzdecode($contents);
        }
    } catch (Exception $exception) {
        throw $exception;
    } finally {
        $zipFile->close();
    }
}

$zipContents = file_get_contents(__DIR__ . '/issue62.zip');
$stream = \GuzzleHttp\Psr7\stream_for($zipContents);

foreach(extractDataFromZip((string) $stream) as $entryName => $content){
    var_dump([$entryName => $content]);
}
4ubi commented 4 years ago

the problem was rights. Before exporting the files, I decided to create a temporary directory with the rights as in the archive. Thanks again for opening my eyes. Rays of gratitude from Siberia)