Загруженные docx файлы превращаются в zip - PullRequest
4 голосов
/ 20 января 2010

В настоящее время я использую symfony 1.4 и хотел бы разрешить пользователям загружать файлы Microsoft Word docx.Используя приведенный ниже виджет sfWidgetFormInputFile и sfValidatorFile, пользователи могут выбирать и успешно загружать свои файлы docx с помощью простой веб-формы.

$this->widgetSchema['file_name'] = new sfWidgetFormInputFile(array('label' => 'File'));

$this->validatorSchema['file_name'] = new sfValidatorFile(array(
  'required'   => true,
  'path'       => sfConfig::get('sf_upload_dir').DIRECTORY_SEPARATOR.sfConfig::get('app_dir_file_sharing').DIRECTORY_SEPARATOR,
  'mime_types' => array('application/msword',
                        'application/vnd.ms-word',
                        'application/msword',
                        'application/msword; charset=binary')
), array(
    'invalid'    => 'Invalid file.',
    'required'   => 'Select a file to upload.',
    'mime_types' => 'The file must be a supported type.'
));

Проблема заключается в том, что после загрузки файла расширение изменяется на .zipи файл содержит дерево файлов XML-файлов.Насколько я понимаю, это связано с тем, что Office 2007 теперь использует форматы файлов Open xml.Есть ли способ предотвратить это, используя symfony или PHP?

Ответы [ 4 ]

6 голосов
/ 20 января 2010

Проблема в контент-нюхании. Новые форматы Office представляют собой файлы .zip, и при загрузке содержимое прослушивается, браузер идентифицирует его как файл ZIP и устанавливает заголовок Content-Type как таковой. Аналогично, при загрузке, если ваш сервер не установит правильный заголовок HTTP-ответа Content-Type, браузер будет считать, что это ZIP-файл.

5 голосов
/ 26 января 2010

Symfony 1.3+ имеет опцию mime_type_guessers для sfValidatorFile , которая позволяет вам определять свой собственный mime-тип guesser, который вызывается из PHP, или использовать сборку в guesser. Вызов любого из 3 встроенных guessers типа mime находит правильный тип файла для docx и сохраняет расширение файла docx.

Вот обновленный код, использующий guessFromFileinfo:

$this->validatorSchema['file_name'] = new sfValidatorFile(array(
'required'   => true,
'path'       => sfConfig::get('sf_upload_dir').DIRECTORY_SEPARATOR.sfConfig::get('app_dir_file_sharing').DIRECTORY_SEPARATOR,
'mime_type_guessers' => array('guessFromFileinfo'),
'mime_types' => array('application/msword',
                    'application/vnd.ms-word',
                    'application/msword',
                    'application/msword; charset=binary')
), array(
    'invalid'    => 'Invalid file.',
    'required'   => 'Select a file to upload.',
    'mime_types' => 'The file must be a supported type.'
));
4 голосов
/ 20 января 2010

Кажется, это ошибка в обнаружении типов файлов Symfony. Обходной путь описан.

1 голос
/ 17 января 2013

Предлагаемое использование mime_type_guessers использует несуществующую функцию. Если вы хотите использовать метод sfValidatorFile, вы должны написать array(array('sfValidatorFile', 'guessFromFileinfo')). Предлагаемое решение вообще не использует обнаружение MIME-типа и приводит к проблемам с классическим форматом Excel в моей системе.

Я исправил проблему, расширив класс sfValidatorFile и изменив метод getMimeType.

Создайте новый файл msValidatorFile.class.php в папке lib:

<?php

class msValidatorFile extends sfValidatorFile
{
  protected function getMimeType($file, $fallback)
  {
    $arrayZips = array( "application/zip", 
                        "application/x-zip", 
                        "application/x-zip-compressed");
    $officeTypes = array(
        "application/vnd.ms-word.document.macroEnabled.12",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 
        "application/vnd.openxmlformats-officedocument.wordprocessingml.template", 
        "application/vnd.ms-powerpoint.template.macroEnabled.12", 
        "application/vnd.openxmlformats-officedocument.presentationml.template", 
        "application/vnd.ms-powerpoint.addin.macroEnabled.12", 
        "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", 
        "application/vnd.openxmlformats-officedocument.presentationml.slideshow", 
        "application/vnd.ms-powerpoint.presentation.macroEnabled.12", 
        "application/vnd.openxmlformats-officedocument.presentationml.presentation", 
        "application/vnd.ms-excel.addin.macroEnabled.12", 
        "application/vnd.ms-excel.sheet.binary.macroEnabled.12", 
        "application/vnd.ms-excel.sheet.macroEnabled.12", 
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 
        "application/vnd.ms-excel.template.macroEnabled.12", 
        "application/vnd.openxmlformats-officedocument.spreadsheetml.template");

    foreach ($this->getOption('mime_type_guessers') as $method)
    {
      $type = call_user_func($method, $file);

      if (null !== $type && $type !== false)
      {
        if (in_array($type, $arrayZips) && in_array($fallback, $officeTypes))
        {
           return $fallback;
        }
        return strtolower($type);
      }
    }

    return strtolower($fallback);
  }
}

Используйте этот новый валидатор в коде формы:

$this->validatorSchema['file'] = 
    new msValidatorFile(array('required' => false,
                              'path' => sfConfig::get('sf_upload_dir')
                        ));
...