Downloaded docx files turning into zip files

I am currently using symfony 1.4 and want to allow users to download Microsoft Word docx files. Using the sfWidgetFormInputFile and sfValidatorFile widgets below, users can select and successfully upload their docx files using a simple web form.

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

The problem is that after downloading the file, the extension changes to .zip, and the file contains a tree of xml file files. I understand that this is because Office 2007 now uses Open xml files. Is there a way to prevent this using symfony or PHP?

+4
source share
4 answers

Symfony 1.3+ has the mime_type_guessers option for sfValidatorFile , which allows you to define your own type of mime guesser, called, or use build in guessing. Calling any of the 3 built-in gadgets of type mime finds the correct file type for docx and supports the docx file extension.

Here is the updated code using the guessFromFileinfo method:

 $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.' )); 
+5
source

The problem is the use of content. The new Office formats are ARE.zip files, and if the content is sniffed during loading, the browser identifies it as a ZIP file and sets the Content-Type header as such. Similarly, at boot time, if your server does not set the correct HTTP Content-Type response header, the browser will assume that it is a ZIP file.

+5
source

The proposed use of mime_type_guessers uses a nonexistent function. If you want to use the sfValidatorFile method, write array(array('sfValidatorFile', 'guessFromFileinfo')) . The proposed solution does not use mime type detection at all and leads to problems with the classic excel format on my system.

I fixed the problem by extending the sfValidatorFile class and changing the getMimeType method.

Create a new msValidatorFile.class.php file in the lib folder:

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

Use this new validator in your form code:

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

All Articles