Ziparchive php архив поврежден

PHP ZipArchive поврежден в Windows

Я использую класс 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:

alt text

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

alt text

Изменить # 2. Эта проблема решена. См. Мой ответ ниже.

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

$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))); 

У меня была такая же проблема, и мое решение было похоже на правильный ответ на этот поток. Когда вы кладете файл в архив, вы не можете иметь абсолютные файлы (файлы, начинающиеся с косой черты), иначе они не будут открываться в 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, '/')); 

а затем он смог открыть в Windows!

Вероятно, та же самая причина pclzip (ответ Plahcinski). Держу пари, он автоматически отбрасывает начальную косую черту.

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

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

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

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 по проблеме).

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

$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; 

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

У меня были проблемы с этим раньше. Попробуйте снять заголовок типа содержимого. вот код, который я разработал для него, который работал в 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)); 

В дополнение к тому, что предложили другие, важно обратить внимание на ваши имена файлов и каталогов, поскольку Windows не обязательно должна соответствовать пути и имена файла Linux. Иногда он также ускользает от них при застегивании. Примеры многочисленны, но самое главное

  • * dot files (. и..), файлы с разницей только в случае (name.txt и NAME.txt),
  • абсолютные пути к файлу (/tmp/file.txt)*.
  • Некоторые другие символы, разрешенные в именах файлов в Windows, могут вызвать проблемы, когда проводник Windows используется для открытия файлов. В моем случае символ “:” был нарушителем сделки, но он много работал, чтобы найти это.
Читайте также:  Все операторы java могут быть перегружен

Итак, прежде чем переходить к использованию с использованием большого количества параметров с помощью exec (‘zip…’), я предлагаю простую процедуру:

  • Найдите папку или файл, который ваш сайт застегнет.
  • run: zip -9 -r -k zip-modified-names.zip/path/to/your/folder
  • обратите внимание на то, что выжимает консоль. В моем случае “:” в именах файлов были удалены.
  • Переместите zip файл на компьютер Windows и попытайтесь открыть его.

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

Также опция -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)); > 

У меня была та же проблема. Этот код работал у меня, но я НАШЕЛ В ПЕРВОЙ ЛИНИИ в моем 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); 
 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 

Это сработало для меня, когда я попробовал вышеуказанные решения.

Читайте также:  Первое вхождение подстроки строку php

Я использовал отметку времени в zip файле. На самом деле файловая система Windows не поддерживает специальные символы, такие как “: \/*? < >|”

После удаления “:” из части времени он работает как шарм

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

У меня была эта проблема в течение часа. Попробовав 10 различных решений, я решил это, убедившись, что script существует после вывода ZIP файла:

 readfile($zip_name); unlink($zip_name); **exit();** 

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

$zipname = "download.zip"; $zip = new ZipArchive; $zip->open($zipname, ZipArchive::CREATE); foreach ($files as $file) < # download file $download_file = file_get_contents($file); addFromString(basename($file), $download_file); $zip->close(); header('Content-Type: application/zip'); //header('Content-disposition: attachment; filename='.$zipname); header("Content-Disposition: attachment; filename=\"$zipname\""); header('Content-Length: ' . filesize($zipname)); readfile($zipname); unlink($zipname); exit; 

Моя проблема заключалась в том, что мои пути к файлам входили в виде строк. Даже при том, что я попытался (string)$path это все еще не работало. Для меня это было использование file_get_contents файла, а затем встроенная функция addFromString которая сделала это для меня.

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

Источник

Оцените статью