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

ользую класс PHP ZipArchive для создания zip-файла, содержащего фотографии, а затем подаю его в браузер для загрузки. Вот мой код:

/**
 * Grabs the order, packages the files, and serves them up for download.
 *
 * @param string $intEntryID 
 * @return void
 * @author Jesse Bunch
 */
public static function download_order_by_entry_id($intUniqueID) {

    $objCustomer = PhotoCustomer::get_customer_by_unique_id($intUniqueID);

    if ($objCustomer):

        if (!class_exists('ZipArchive')):
            trigger_error('ZipArchive Class does not exist', E_USER_ERROR);
        endif;

        $objZip = new ZipArchive();
        $strZipFilename = sprintf('%s/application/tmp/%s-%s.zip', $_SERVER['DOCUMENT_ROOT'], $objCustomer->getEntryID(), time());

        if ($objZip->open($strZipFilename, ZIPARCHIVE::CREATE) !== TRUE):

            trigger_error('Unable to create zip archive', E_USER_ERROR);

        endif;          

        foreach($objCustomer->arrPhotosRequested as $objPhoto):

            $filename = PhotoCart::replace_ee_file_dir_in_string($objPhoto->strHighRes);
            $objZip->addFile($filename,sprintf('/press_photos/%s-%s', $objPhoto->getEntryID(), basename($filename)));

        endforeach;

        $objZip->close();

        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($strZipFilename)).' GMT',  TRUE, 200);
        header('Cache-Control: no-cache', TRUE);
        header('Pragma: Public', TRUE);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT', TRUE);
        header('Content-Length: '.filesize($strZipFilename), TRUE);
        header('Content-disposition: attachment; filename=press_photos.zip', TRUE);

        header('Content-Type: application/octet-stream', TRUE);

        ob_start();
        readfile($strZipFilename);
        ob_end_flush();
        exit;

    else:

        trigger_error('Invalid Customer', E_USER_ERROR);

    endif;

}

Этот код работает очень хорошо со всеми браузерами, кроме IE. В IE файл загружается правильно, но zip-архив пуст. При попытке извлечь файлы Windows сообщает, что zip-архив поврежден. У кого-нибудь была эта проблема раньше?

редактировать Обновление: после предложения от @profitphp я изменил свои заголовки на это:

header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
//header("Content-Description: File Transfer");
//header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"pressphotos.zip\"");
//header("Content-Transfer-Encoding: binary");
header("Content-length: " . filesize($strZipFilename));

Кроме того, вот скриншот ошибки в Windows после открытия с Firefox:

Эта ошибка возникает как в IE, так и в Firefox в Windows. Он отлично работает в Mac. Кроме того, в Windows размер файла выглядит правильно:

Редактировать № 2 Этот вопрос решен. Смотрите мой ответ ниже.

 MaRmAR27 февр. 2015 г., 17:02
Была та же проблема, и этот ответ был решением для меня: [ZIP-архив, отправленный PHP, поврежден] [1] [1]:stackoverflow.com/a/13528263/557311

Ответы на вопрос(13)

нтента. вот код, который я придумал для него, который работал в IE и FF. Обратите внимание на закомментированные строки, у которых были одни и те же проблемы с различными комбинациями из тех, которые были включены.

header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
//header("Content-Description: File Transfer");
//header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"adwords-csv.zip\"");
//header("Content-Transfer-Encoding: binary");
header("Content-length: " . filesize($filename)); 
 Jesse Bunch06 янв. 2011 г., 23:08
Спасибо за ваше время, я обновил эту проблему с дополнительной информацией.
 Jesse Bunch06 янв. 2011 г., 22:56
Я изменил свои заголовки и без кубиков, ZIP-файл по-прежнему «поврежден» в соответствии с Windows, но на моем Mac все нормально.
 Jesse Bunch06 янв. 2011 г., 23:27
Вы правы, когда я копирую этот «испорченный» zip-файл из windows на мой Mac, он открывается без проблем.
 profitphp06 янв. 2011 г., 23:14
ну это не заголовок, наверное, кажется, что-то с Windows по умолчанию Zip Reader. Вы пробовали что-то вроде winrar, чтобы распаковать его? Я просто использовал zip из командной строки в моей реализации, а не класс архива zip. Если худшее становится худшим, вы можете попробовать это.
 profitphp06 янв. 2011 г., 22:58
Постарайтесь, чтобы заголовки выглядели точно так же, как те, которые я опубликовал, того же порядка и все такое. У меня также были подобные проблемы при использовании определенных имен файлов внутри почтового индекса. Придерживайтесь очень основного набора символов. Теперь вы упоминаете окна. Если вы используете Firefox, Chrome и т. Д., В Windows происходит ли то же самое? Это проблема браузера или проблема с читателем zip?

как вы описали. Я обнаружил, что ZipArchive в лучшем случае нестабилен.

Я решил свои проблемы с этой простой библиотекой

http://www.phpconcept.net/pclzip

include_once('libs/pclzip.lib.php');

...

function zip($source, $destination){
$zipfile = new PclZip($destination);
$v_list = $zipfile->create($source, '', $source); }

$ source = папка, которую я хотел заархивировать $ destination = расположение файла zip

Я потратил 2 дня на поиск ZipArchive, а затем решил все проблемы с PCLZip за 5 минут.

Надеюсь, что это поможет вам и всем, кто столкнулся с этой проблемой (так как она находится рядом с лучшим результатом Google по данной проблеме).

 Phoca17 июл. 2017 г., 18:34
Отличная библиотека. Чтобы использовать его на сервере PHP7.1, просто измените метод «PclZip» на «__construct» и добавьте «(int)», где требуется целое число.
 Samir Sabri02 мар. 2015 г., 14:36
здорово! очень просто и прямо к делу
 Dev.Jaap16 апр. 2012 г., 20:55
в среде окна. На моей веб-странице, к сожалению, он работал очень хорошо: он заархивировал только один файл вместо нескольких файлов,
 Dev.Jaap10 апр. 2012 г., 20:35
Thx, эта библиотека, кажется, работает очень хорошо!
 Flion26 авг. 2013 г., 16:02
работал на меня на окнах. как вы сказали, почти час, глядя на ZipArchive, и это сработало за 2 минуты. TNX!

но в моем случае мне нужно написать ob_clean (); перед первым заголовком (''); потому что некоторые файлы, которые я включаю перед печатью некоторых символов, которые разбивают zip-файл на windows

$zip=new ZipArchive();
$zip->open($filename, ZIPARCHIVE::CREATE);
$zip->addFile($file_to_attach,$real_file_name_to_attach);
$zip->close();

ob_clean();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="file.zip"');
readfile($filename);
exit;
 Neman05 нояб. 2016 г., 15:30
Спасибо, у меня работает!
 llanato27 июл. 2015 г., 15:34
Это сработало для меня, попробовал все остальное без удачи.

таких как подчеркивание, вызывает проблемы, поскольку ZipArchive требует кодированных имен записей в IBM850. Смотрите комментарии в онлайн-руководстве по PHP:http://www.php.net/manual/en/function.ziparchive-addfile.php#95725 .

 Nathan Hangen21 мар. 2014 г., 15:38
У меня было длинное имя почтового файла с пробелами, тире и символами даты. Оказывается, когда я изменил имена файлов на что-то простое, например export.zip, все заработало нормально.

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

Так получилось, что не потому, что он (Джесси Банч, выбранный ответ на момент написания этой статьи) удалил содержащую папку, а потому, что удалил начальный слеш.

Я исправил проблему, изменив

$zip->addFile($file, $file); // $file is something like /path/to/file.png

в

// we make file relative by removing beginning slash so it will open in Windows
$zip->addFile($file, ltrim($file, '/'));

и тогда его удалось открыть в винде!

Вероятно, это та же самая причина, по которой работает pclzip (ответ Плахцинского). Бьюсь об заклад, он автоматически удаляет начало слэша.

Я бы не понял это безконкретный комментарий на PHPZipArchive::addFile страница документации.

 Jake N15 мар. 2016 г., 23:00
Это было проблемой для меня, очень помогло
            ob_clean(); //very important
            // http headers for zip downloads
            header("Pragma: public");
            header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
            header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
            header("Cache-Control: public");
            header('Content-Type: application/x-download');
            header("Content-Disposition: attachment; filename=\"filename.zip\"");
            header("Content-Length: ".filesize($filepath ));

            @readfile($filepath );
            unlink($filepath);  //very important
            exit;//very important

система Windows не поддерживает специальные символы, такие как": \ / *? <> |"

После удаления":" из временной части это работает как очарование

если кто-то еще несколько часов бьет его / ее по кирпичной стене и страдает, как я. У меня была та же проблема, и ни одно из решений не помогло, пока я не понял, что я загружаю некоторые библиотеки в свой PHP, и одна из них имеет пустую строку после кода?>. При звонке в библиотеку сinclude(/path/to/lib/lib.php); в браузер была выведена пустая строка, в результате чего zip был классифицирован как испорченный Windows. (У Winzip, Total Commander и т. Д. С этим проблем не было). Поэтому убедитесь, что нет импортированной библиотеки или, если она есть, в ней нет пробелов или пустых строк ....

 Jesse Bunch13 февр. 2015 г., 02:26
О да. Это сделает это.

но я должен был поставить первую строку в моем php-файле! Если я поместил код в середине файла, я бы не работал. Может быть, какие-то проблемы с кодировкой ?!

// Prepare File
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
$zip->open($file, ZipArchive::OVERWRITE);

// Staff with content
$zip->addFile($filepathOnServer, 'mypic.jpg');

// Close and send to users
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="filename.zip"');
readfile($file);
unlink($file);

я решил, что после вывода ZIP-файла сценарий существует:

            readfile($zip_name);
            unlink($zip_name);
            **exit();**
Решение Вопроса

после долгих раздоров я разобрался с проблемой. Проблема связана со следующей строкой кода:

$objZip->addFile($filename,sprintf('/press_photos/%s-%s', $objPhoto->getEntryID(), basename($filename)));

По какой-то причине/press_photos/ часть этого пути для локального (внутреннего) имени файла внутри zip-архива заставляла Windows думать, что zip-файл поврежден. После изменения строки, чтобы она выглядела так, как показано ниже, Windows правильно открыла zip-файлы. Уф.

$objZip->addFile($filename,sprintf('%s-%s', $objPhoto->getEntryID(), basename($filename)));
 doub1ejack29 мар. 2012 г., 19:00
Я успешно переименовал файл после добавления в архив. Это хорошее решение, если вам не нужно поддерживать структуры каталогов в вашем архиве: $ zip-> addFile ($ uri, basename ($ uri)); $ zip-> renameName (basename ($ uri), str_replace ('_', '-', basename ($ uri)));

Измените свой код:

 header('Content-Length: '.filesize($strZipFilename), TRUE);

С участием:

header('Content-Length: '.file_get_contents($strZipFilename));
 CWSpear15 сент. 2017 г., 21:06
Это выведет все содержимое файла какContent-Length, а не фактический размер (что они хотят). Это определенно не то, что они хотят сделать (и не имеют отношения к проблеме). У них это правильно.

важно обратить внимание на имена файлов и каталогов поскольку Windows не обязательно любит путь и имена файлов Linux. Это иногда также ускользает от них по-разному при архивировании. Примеров много, но самое главное

* точечные файлы (. и ..), файлы только с регистрационными различиями (name.txt и NAME.txt),абсолютные пути к файлам (/tmp/file.txt)*.Некоторые другие символы, которые разрешены в именах файлов в Windows, могут вызывать проблемы при использовании Проводника Windows для открытия файлов. В моем случае характер «:» был решающим фактором, но потребовалось много работы, чтобы выяснить это.

Поэтому, прежде чем вы возобновите использование множества параметров через exec ('zip ...'), я предлагаю выполнить простую процедуру:

Найдите папку или файл, ваш сайт застегивается.бегать:zip -9 -r -k zip-modified-names.zip / путь / к / вашей / папкеобратите внимание на то, что консоль выплевывает. В моем случае ':' в именах файлов были удалены.Переместите zip-файл на компьютер с Windows и попробуйте открыть его.

Если это работает, возможно, лучше удалить символы, которые были удалены опцией -k, из имен файлов / каталогов, попробуйте выполнить обычную архивацию.Обратите внимание, что некоторые параметры, такие как -k, имеют побочные эффекты. В этом случае -k противоречит опции -q (для ссылок sym).

Также опция -k может сделать ваши имена файлов нечитаемыми. В моем случае мои файлы были названы в зависимости от времени создания (например, 10: 55: 39.pdf), чтобы упростить поиск нужной записи в архивах, но опция -k превратила ее в 105539.pdf, который не легко читается пользователями. Поэтому я изменил имена на 10_55_39.pdf, который открывается в Windows без использования опции -k, но все еще доступен для чтения.

В дополнение к этому, использование PCLZip сделает вашу жизнь намного проще, так как вы можете добавить сразу всю папку, а также изменить путь к файлам в одной простой строке. В моем случае я удаляю / tmp / directory / из моих zip-файлов со вторым и третьим параметрами, что позволяет избежать еще одной проблемы совместимости Windows (имея абсолютный путь в zip-файлах):

$v_list = $zip->create( $sourceFolder, PCLZIP_OPT_REMOVE_PATH, $sourceFolder . DIRECTORY_SEPARATOR);
if ($v_list == 0) {
    throw new \Exception($zip->errorInfo(true));
}

Ваш ответ на вопрос