Zlib ломает CodeIgniter Zip Downloader и PHPExcel - PullRequest
0 голосов
/ 16 января 2019

Я сталкиваюсь с проблемой, когда, если на веб-сервере включено сжатие Zlib, загрузка любого zip-файла с помощью функции CodeIgniter force_download в системном файле download_helper.php нарушает архивный файл и не позволяет пользователям открыть его.

enter image description here

Вот функция force_download для сжатых файлов после сжатия XLSX файлов в ней:

    function force_download($filename = '', $data = '')
    {
        if ($filename == '' OR $data == '')
        {
            return FALSE;
        }

        // Try to determine if the filename includes a file extension.
        // We need it in order to set the MIME type
        if (FALSE === strpos($filename, '.'))
        {
            return FALSE;
        }

        // Grab the file extension
        $x = explode('.', $filename);
        $extension = end($x);

        // Load the mime types
        if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
        {
            include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
        }
        elseif (is_file(APPPATH.'config/mimes.php'))
        {
            include(APPPATH.'config/mimes.php');
        }

        // Set a default mime if we can't find it
        if ( ! isset($mimes[$extension]))
        {
            $mime = 'application/octet-stream';
        }
        else
        {
            $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
        }

        // Generate the server headers
        if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header("Content-Transfer-Encoding: binary");
            header('Pragma: public');
            header("Content-Length: ".strlen($data));
        }
        else
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header("Content-Transfer-Encoding: binary");
            header('Expires: 0');
            header('Pragma: no-cache');
            header("Content-Length: ".strlen($data));
        }

        exit($data);
    }

Включение Zlib также нарушает работу PHPExcel, создавая искаженные символы в файлах Excel, как вы можете видеть на этом изображении.

enter image description here

Функция загрузки PHPExcel для одного XLSX файла. Вот суть всех функций генератора, почтового индекса и загрузчика Excel https://gist.github.com/TheWebAuthor/5773e56086df4317c7cf54aab45df328

ob_end_clean();                    
header('Content-Description: File Transfer');                            
header('Content-Type: application/vnd.ms-excel');                            
header('Content-Disposition: attachment; filename=' .$fileinfo['filename'] . '_' . $customerId . '_' . date("mdy") . '.xls');              
header('Content-Transfer-Encoding: binary');                            
header('Expires: 0');                            
header('Cache-Control: must-revalidate');                            
header('Pragma: public');                            
header('Content-Length: ' . filesize($file));                            
ob_clean();                            
flush();                            
readfile($file);

Существует ли правильный обходной путь, позволяющий Zlib не нарушать эти функции?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

а) application/vnd.ms-excel для формата XLS BIFF8; для XLSX используйте:

header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');

b) файл ZIP может быть неправильно упакован или $mimes[$extension] может не содержать application/zip. Трудно сказать, не увидев функцию, которая его упаковывает, заголовки ответа и, в конечном итоге, заголовок файла текущего вывода.

0 голосов
/ 24 января 2019

Вы не четко указали все детали вашего скрипта, но вы начинаете с описания "zip-файла" и ссылки на "архивы". Однако тот небольшой код, который вы опубликовали, отправляет заголовок типа контента для файла Excel. Если вы отправляете zip-файл в браузер, но сообщаете браузеру, что его тип MIME application / vnd.ms-excel , то это может быть вашей проблемой.

Рассматривали ли вы только использование функции force_download? Этот контроллер работает для меня независимо от того, является ли файл Excel или ZIP:

public function download() {
    $filepath = "/path/to/file.zip";
     // or you can send an Excel file
    $filepath = "/path/to/file.xls";

    $filename = basename($filepath);

    $data = file_get_contents($filepath);

    $this->load->helper('download');
    force_download($filename, $data);
}

Функция force_download имеет встроенный код для определения правильного типа MIME на основе расширения файла . В зависимости от вашей версии Codeigniter вам может потребоваться указать третий параметр TRUE .

Я повторил проблему «искаженного символа», которую вы описываете, установив mime-тип application / vnd.ms-excel , но отправив ZIP-файл. И наоборот, я успешно загрузил файлы ZIP и XLS, просто используя функцию force_download.

EDIT Увидев некоторый код, я хотел бы предложить вам переработать логику вокруг строки 229 , так как немного неловко проверять count($result) внутри цикла foreach. Вы можете проверить это перед входом в цикл foreach.

Что еще более важно, вам не удалось инициализировать $download_data как массив перед назначением элементов массива. В зависимости от вашей среды и настроек error_reporting, это может вызвать E_NOTICE или E_WARNING, которые вызывают дополнительный вывод, прежде чем вы начнете выводить содержимое вашего zip-файла. Если ваш код заканчивает выводить нежелательные символы до того, как он начинает выводить фактические двоичные данные вашего zip-архива, это повредит файл. Другая возможность состоит в том, что ссылка на неопределенную переменную вызовет ошибку E_NOTICE для вывода на стандартный вывод, что может привести к сбою любых последующих команд заголовка, поскольку вы не можете отправлять команды заголовка после начала вывода текста.

Другая возможность - неверный тип пантомимы. Ваша версия Codeigniter довольно старая, но я думаю, что это вряд ли проблема. Если вы можете, попробуйте проверить заголовки ответа, отправленные в ваш браузер, чтобы узнать, являются ли они application / x-gzip или application / zip или что-то еще.

Наконец, вы должны проверить настройку compress_output в appilcation / config.php . Пожалуйста, обратите внимание на комментарии там:

/*
|--------------------------------------------------------------------------
| Output Compression
|--------------------------------------------------------------------------
|
| Enables Gzip output compression for faster page loads.  When enabled,
| the output class will test whether your server supports Gzip.
| Even if it does, however, not all browsers support compression
| so enable only if you are reasonably sure your visitors can handle it.
|
| Only used if zlib.output_compression is turned off in your php.ini.
| Please do not use it together with httpd-level output compression.
|
| VERY IMPORTANT:  If you are getting a blank page when compression is enabled it
| means you are prematurely outputting something to your browser. It could
| even be a line of whitespace at the end of one of your scripts.  For
| compression to work, nothing can be sent before the output buffer is called
| by the output class.  Do not 'echo' any values with compression enabled.
|
*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...