我目前正在使用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?
答案 0 :(得分:6)
问题是Content-Sniffing。新的Office格式为.zip文件,如果在上传时内容被嗅探,浏览器会将其识别为ZIP文件并设置Content-Type标头。同样,除非您的服务器设置正确的Content-Type HTTP响应标头,否则在下载时,浏览器将假定这是一个ZIP文件。
答案 1 :(得分:5)
Symfony 1.3+对sfValidatorFile有一个选项mime_type_guessers
,它允许你定义你自己的mime类型guesser PHP可调用或使用guesser中的构建。调用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.'
));
答案 2 :(得分:4)
在Symfony的文件类型检测中似乎是bug。描述了一种解决方法。
答案 3 :(得分:1)
建议使用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')
));