PHP - ZipArchive () разрешает проблемы с очисткой - PullRequest
0 голосов
/ 07 сентября 2018

У меня постоянно возникают проблемы с разрешением - я разархивирую файл (эта часть в порядке) и перемещает содержимое в папку для записи.

Я использую простой код:

$zip  = new ZipArchive( );
$x    = $zip->open( $file );
if ( $x === true ) {

  $zip->extractTo( $target );
  $zip->close( );
  unlink( $file );

  rmove( __DIR__ . '/' . $target . '/dist', __DIR__ );
} else {

  die( "There was a problem. Please try again!" );
}

, где rmove() - простая рекурсивная функция, которая перебирает содержимое и применяет rename() к каждому файлу.

Проблема в том, что разархивирование проходит хорошо, файлы копируются, но не перемещаются - удалите из временной папки. До сих пор я читал, что это может быть вызвано отсутствием разрешения на запись в разархивированные файлы во время переименования.

Как контролировать эти разрешения во время распаковки?

Обновление: содержимое rmove ():

function rmove( $src, $dest ) {

    // If source is not a directory stop processing
    if ( ! is_dir( $src ) ) return false;

    // If the destination directory does not exist create it
    if ( ! is_dir( $dest ) ) {

      if ( ! mkdir( $dest ) ) {
        // If the destination directory could not be created stop processing
        return false;
      }
    }

    // Open the source directory to read in files
    $i = new DirectoryIterator( $src );
    foreach( $i as $f ) {

      if ( $f->isFile( ) ) {

        echo $f->getRealPath( ) . '<br/>';
        rename( $f->getRealPath( ), "$dest/" . $f->getFilename( ) );
      } else if ( ! $f->isDot( ) && $f->isDir( ) ) {

        rmove( $f->getRealPath( ), "$dest/$f" );
        unlink( $f->getRealPath( ) );
      }
    }
    unlink( $src );
}

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Мне просто интересно узнать о каталоге $ target. '/ Dist'.Я предполагаю, что каталог 'dist' исходит из архива.Указав, что я вижу, что функция 'rmove' склонна копировать файл в каталог назначения до его создания.Ваш код предполагает, что каталог заменит файлы в итераторе.Если путь к файлу заменяет каталог, каталог назначения не будет существовать для копирования файла.

Я бы предложил вам альтернативную функцию для вашей пользовательской написанной рекурсивной функции 'rmove', которая является RecursiveDirectoryIterator.

http://php.net/manual/en/class.recursivedirectoryiterator.php

Позвольте мне упростить ваш код с помощью RecursiveDirectoryIterator следующим образом

$directory = new \RecursiveDirectoryIterator( __DIR__ . '/' . $target . '/dist', RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directory);

foreach ($iterator as $f) {

    if($f->isFile()){
        if(!empty($iterator->getSubpath())) 
              @mkdir(__DIR__."/" . $iterator->getSubpath(),0755,true);

        rename($f->getPathname(), __DIR__."/" . $iterator->getSubPathName());

    }

}

Проверьте, по-прежнему ли вы получаете ошибку разрешения.

0 голосов
/ 11 сентября 2018

Насколько я знаю, ZipArchive::extractTo не устанавливает никаких специальных разрешений на запись / удаление, поэтому у вас должен быть полный доступ к извлеченным файлам.

Проблема с вашим кодом - функция rmove. Вы пытаетесь удалить каталоги с помощью unlink, но unlink удаляет файлы. Вы должны использовать rmdir для удаления каталогов.

Если мы исправим эту проблему, ваша rmove функция будет работать нормально.

function rmove($src, $dest) {
    // If source is not a directory stop processing
    if (!is_dir($src)) {
        return false;
    }
    // If the destination directory does not exist create it
    if (!is_dir($dest) && !mkdir($dest)) {
        return false;
    }
    // Open the source directory to read in files
    $contents = new DirectoryIterator($src);
    foreach ($contents as $f) {
        if ($f->isFile()) {
            echo $f->getRealPath() . '<br/>';
            rename($f->getRealPath(), "$dest/" . $f->getFilename());
        } else if (!$f->isDot() && $f->isDir()) {
            rmove($f->getRealPath(), "$dest/$f");
        }
    }
    rmdir($src);
}

Вам не нужно удалять каждую подпапку в цикле, rmdir в конце удалит все папки, так как это рекурсивная функция.

Если вы все еще не можете удалить содержимое папки, возможно, у вас недостаточно прав. Я не думаю, что это очень вероятно, но в этом случае вы можете попробовать chmod.

...