ZipArchive: `не удалось открыть поток: является каталогом`

Я продолжаю получать failed to open stream: Is a directory ошибка при попытке разархивировать файл с помощью PHP.

Обычно это проблема с путем назначения.

Тем не менее, в моем случае, назначение в порядке: я могу разархивировать разные файлы, используя один и тот же код, или разархивировать один и тот же файл без PHP.

Документация ZipArchive::extract для не помогла. Также не было других тем в этом сообщении об ошибке.


К вашему сведению, это вопрос и ответы.


Вот исходный код в соответствии с просьбой в комментарии. Я публично поделился ссылкой Dropbox, видя, как этот вопрос зависит от формата ввода ZIP (/ Путь в ZIP-файле, см. ответ.)

/** Config **/
$url = 'https://www.dropbox.com/sh/nx5792q9syppaoo/AAAJZBWlGNAd_EkmQaFvEwe0a?dl=1';

/** Where to save **/
$zipped = ABSPATH . 'tmp/updates/dialogues.zip';    /* Keep in mind this is public-facing. */
$outputdirectory = ABSPATH . 'tmp/updates/testing'; /* The trailing slash is optinal. */

/** Download the dialogues **/
echo 'Fetching the dialogues...<br>';
if ( ( $dropboxfile = fopen( $url, 'r' ) ) === FALSE ) {    /* == has higher precedent over = */
    echo 'FATAL ERROR: could not open Dropbox file.';
    die();
} else if ( file_put_contents( $zipped, $dropboxfile ) === FALSE ) {
    echo 'FATAL ERROR: could not copy Dropbox file.';
    die();
}
echo "Dialogues downloaded as zip OK. (See {$zipped})<br>";


/** Unzip the dialogues **/
print 'Unzipping...<br>';
$zip = new ZipArchive;
$res = $zip->open( $zipped );
if ( $res === TRUE ) {

    // Does not work
    // $zip->extractTo( ABSPATH . 'tmp/updates/testing' );

    // Works
    for( $i = 0 ; $i < $zip->numFiles ; $i++ ) {
        if ( $zip->getNameIndex( $i ) != '/' && $zip->getNameIndex( $i ) != '__MACOSX/_' ) {
            print $zip->getNameIndex( $i ) . '<br>';
            $zip->extractTo( $outputdirectory, array($zip->getNameIndex($i)) );
        }
    }

    $zip->close();
    print 'Done unzipping.<br>';
} else {
    print 'FATAL ERROR: unzipping failed.';
}

1 ответ

Как оказалось, у меня был / "папка" внутри архива ZIP.

Это подтверждается просмотром ZIP-архива через командную строку. например, на OS X, используя unzip -vl dialogues.zip дал мне это:

Archive:  dialogues.zip
 Length   Method    Size  Ratio   Date   Time   CRC-32    Name
--------  ------  ------- -----   ----   ----   ------    ----
       0  Defl:N        2   0%  08-22-15 12:07  00000000  /
    2154  Defl:N     1064  51%  06-08-15 15:18  602c6793  dialogue001-en.txt
    ...
    4379  Defl:N     1793  59%  08-21-15 13:56  75e1ef52  dialogue106-en.txt
      70  Defl:N       39  44%  08-22-15 12:07  985af458  __MACOSX/_
--------          -------  ---                            -------
  775512           343864  56%                            312 files

Файл загружен из Dropbox, и я бы предпочел работать с ним как есть.

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

print 'Unzipping...<br>';
$zip = new ZipArchive;
$res = $zip->open( $zipped );
if ( $res === TRUE ) {
    // 
    for( $i = 0 ; $i < $zip->numFiles ; $i++ ) {
        if ( $zip->getNameIndex( $i ) != '/' && $zip->getNameIndex( $i ) != '__MACOSX/_' ) {
            print $zip->getNameIndex( $i ) . '<br>';
            $zip->extractTo( $tempdirectory, array($zip->getNameIndex($i)) );
        }
    }
    $zip->close();
    print 'Done unzipping.<br>';
} else {
    print 'FATAL ERROR: unzipping failed.';
}

Нигде не видел этого документально и потратил на это почти час. Надеюсь, это кому-нибудь поможет.

Я до сих пор не ясно, является ли / ссылка внутри ZIP-файла верна. (Комментарии приветствуются.)

Другие вопросы по тегам