【问题标题】:Uploaded docx files turning into zip上传的 docx 文件变成 zip
【发布时间】:2011-01-07 10:17:36
【问题描述】:

我目前正在使用 symfony 1.4,并希望允许用户上传 Microsoft Word docx 文件。使用下面的 sfWidgetFormInputFile 小部件和 sfValidatorFile,用户可以使用简单的 Web 表单选择并成功上传他们的 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 来防止这种情况发生?

【问题讨论】:

  • 这也适用于 xlsx 文件

标签: php apache symfony1 symfony-1.4


【解决方案1】:

在 Symfony 的文件类型检测中似乎是 bug。描述了一种解决方法。

【讨论】:

    【解决方案2】:

    问题在于内容嗅探。新的 Office 格式是 .zip 文件,如果在上传时会嗅探内容,浏览器会将其识别为 ZIP 文件并设置 Content-Type 标头。同样,下载时除非您的服务器设置了正确的 Content-Type HTTP 响应标头,否则浏览器将假定这是一个 ZIP 文件。

    【讨论】:

    • 是的,新的 Office 2007 格式是已压缩的 XML 文件。
    【解决方案3】:

    Symfony 1.3+ 有一个选项mime_type_guessers 用于sfValidatorFile,它允许您定义自己的 mime 类型猜测器 PHP 可调用或使用内置猜测器。调用 3 个内置的 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】:

      mime_type_guessers 的建议用法使用了一个不存在的函数。 如果你想使用 sfValidatorFile 方法,你应该写array(array('sfValidatorFile', 'guessFromFileinfo'))。 建议的解决方案根本不使用 mime 类型检测,导致我的系统上的经典 excel 格式出现问题。

      我通过扩展 sfValidatorFile 类并更改 getMimeType 方法解决了这个问题。

      在你的 lib 文件夹中创建一个新的 msValidatorFile.class.php 文件:

      <?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')
                              ));
      

      【讨论】:

        猜你喜欢
        • 2017-08-12
        • 2013-07-20
        • 2012-06-04
        • 2015-10-01
        • 2014-04-16
        • 1970-01-01
        • 2013-10-24
        • 2019-01-22
        • 2017-05-24
        相关资源
        最近更新 更多