When uploading a file based on Yii 2.0, the list of file extensions that can be uploaded has been added: .docx, and the solution is still not allowed to upload
1. List of file extensions that can be uploaded: ogg, pdf, xml, zip, gz, mp4, mp3, wav, webm, gif, jpeg, jpg, png, webp, SVG, SVGZ, TIFF, CSS, CSV, TXT, VCF, VCARD, MOV, QT, MKV, MK3D, MKA, MKS, WMV, FLV, DOC
2. The upload extension is: .doc, the upload is successful, as shown in Figure 1
{
"code": 10000,
"message": "上传资源成功",
"data": {
"items": [
{
"original_file_name": "原始凭证单据(1).doc",
"relative_path": "/tmp/2019/12/20/1576810484.4368.436639923.doc",
"url": "http://127.0.0.1/pcs-api/storage/tmp/2019/12/20/1576810484.4368.436639923.doc"
}
]
}
}
3. Upload a file with the extension: .docx, the upload failed, prompt: not allowed, as shown in Figure 2
{
"code": 226004,
"message": "数据验证失败:只允许使用以下文件扩展名的文件:ogg, pdf, xml, zip, gz, mp4, mp3, wav, webm, gif, jpeg, jpg, png, webp, svg, svgz, tiff, css, csv, txt, vcf, vcard, mov, qt, mkv, mk3d, mka, mks, wmv, flv, doc, docx。"
}
4. Edit the core file of the Yii 2.0 framework: validators/filevalidator.php, modify the method: validateExtension($file) to start debugging, request again, output: 2, as shown in Figure 3
/**
* Checks if given uploaded file have correct type (extension) according current validator settings.
* @param UploadedFile $file
* @return bool
*/
protected function validateExtension($file)
{
$extension = mb_strtolower($file->extension, 'UTF-8');
if ($this->checkExtensionByMimeType) {
$mimeType = FileHelper::getMimeType($file->tempName, null, false);
if ($mimeType === null) {
echo 1;
exit;
return false;
}
$extensionsByMimeType = FileHelper::getExtensionsByMimeType($mimeType);
if (!in_array($extension, $extensionsByMimeType, true)) {
echo 2;
exit;
return false;
}
}
if (!in_array($extension, $this->extensions, true)) {
echo 3;
exit;
return false;
}
return true;
}
5. CheckExtensionByMimeType: Whether to judge the file extension by the mime type of the file. If the file extension determined by MIME is not the same as the extension of the given file, the file will be considered invalid. The default is true, which means that the above detection is performed. Print the output in turn: $mimeType, $extensionsByMimeType, and $extension, the values are:
application/zip
Array
(
[0] => zip
)
docx
6. Analysis results, since: CheckExtensionByMimeType is not explicitly set, the default is true, and the file extension (zip) determined by MIME is different from the extension (DOCX) of a given file, then the file will be considered invalid. Edit the core file of the Yii 2.0 framework: helpers/basefileHelper.php, modify the method: getmimeType, to start debugging, and print the output in turn: $file, $result, and its values are:
/**
* Determines the MIME type of the specified file.
* This method will first try to determine the MIME type based on
* [finfo_open](http://php.net/manual/en/function.finfo-open.php). If the `fileinfo` extension is not installed,
* it will fall back to [[getMimeTypeByExtension()]] when `$checkExtension` is true.
* @param string $file the file name.
* @param string $magicFile name of the optional magic database file (or alias), usually something like `/path/to/magic.mime`.
* This will be passed as the second parameter to [finfo_open()](http://php.net/manual/en/function.finfo-open.php)
* when the `fileinfo` extension is installed. If the MIME type is being determined based via [[getMimeTypeByExtension()]]
* and this is null, it will use the file specified by [[mimeMagicFile]].
* @param bool $checkExtension whether to use the file extension to determine the MIME type in case
* `finfo_open()` cannot determine it.
* @return string the MIME type (e.g. `text/plain`). Null is returned if the MIME type cannot be determined.
* @throws InvalidConfigException when the `fileinfo` PHP extension is not installed and `$checkExtension` is `false`.
*/
public static function getMimeType($file, $magicFile = null, $checkExtension = true)
{
if ($magicFile !== null) {
$magicFile = Yii::getAlias($magicFile);
}
if (!extension_loaded('fileinfo')) {
if ($checkExtension) {
return static::getMimeTypeByExtension($file, $magicFile);
}
throw new InvalidConfigException('The fileinfo PHP extension is not installed.');
}
$info = finfo_open(FILEINFO_MIME_TYPE, $magicFile);
if ($info) {
$result = finfo_file($info, $file);
finfo_close($info);
if ($result !== false) {
print_r($file);
echo "\n";
echo "\n";
print_r($result);
exit;
return $result;
}
}
return $checkExtension ? static::getMimeTypeByExtension($file, $magicFile) : null;
}
E:\phpuploadtmp\phpF3BE.tmp
application/zip
7. The fileinfo function of the PHP 7.2 language itself: FINFO_FILE, the file of .docx cannot be accurately identified (feeling), but .docx is a compressed XML format, which is why The reason for file_info() returns application_zip (exactly correct). Create a new file: finfo_file.php, output: application/zip, as shown in Figure 4
8. Refer to the official document:https://www.php.net/manual/zh/function.finfo-file.php, there exists MS Office 2007 extension (PPTX, XLSX, DOCX) does not have the default MIME type, they have application/zip MIME Types of solutions, in essence, have done a special treatment to safely prevent fake extensions. as shown in Figure 5
9. Create a new class file: common/logics/upload.php, inherit to \yii\validators\filevalidator, to overwrite the method of verifying the extension: validateExtension($file)
* @since 1.0
*/
class FileValidator extends \yii\validators\FileValidator
{
/**
* Checks if given uploaded file have correct type (extension) according current validator settings.
* @param UploadedFile $file
* @return bool
* @throws InvalidConfigException when the `fileinfo` PHP extension is not installed and `$checkExtension` is `false`.
*/
protected function validateExtension($file)
{
$extension = mb_strtolower($file->extension, 'UTF-8');
if ($this->checkExtensionByMimeType) {
$mimeType = FileHelper::getMimeType($file->tempName, null, false);
if ($mimeType === null) {
return false;
}
$extensionsByMimeType = FileHelper::getExtensionsByMimeType($mimeType);
if (!in_array($extension, $extensionsByMimeType, true)) {
// MS Office 2007 扩展(docx、xlsx),其 MIME 类型为 application/zip 的特殊处理
$msMimeTypes = ['application/zip'];
$msExtensions = ['docx', 'xlsx'];
if (!(in_array($mimeType, $msMimeTypes) && in_array($extension, $msExtensions)))
{
return false;
}
}
}
if (!in_array($extension, $this->extensions, true)) {
return false;
}
return true;
}
}
docx
application/zip
xlsx
application/zip
pptx
application/vnd.openxmlformats-officedocument.presentationml.presentation
10. The verification rule of the upload model, before is the validator alias: file, now adjusted to: Common\Components\Validators\FileValidator
public function rules()
{
return [
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => Yii::$app->params['pcsApi']['asset']['upload']['extensions'], 'mimeTypes' => Yii::$app->params['pcsApi']['asset']['upload']['mimeTypes'], 'minSize' => Yii::$app->params['pcsApi']['asset']['upload']['minSize'], 'maxSize' => Yii::$app->params['pcsApi']['asset']['upload']['maxSize'], 'maxFiles' => Yii::$app->params['pcsApi']['asset']['upload']['maxFiles']],
];
}
public function rules()
{
return [
[['files'], 'common\components\validators\FileValidator', 'skipOnEmpty' => false, 'extensions' => Yii::$app->params['pcsApi']['asset']['upload']['extensions'], 'mimeTypes' => Yii::$app->params['pcsApi']['asset']['upload']['mimeTypes'], 'minSize' => Yii::$app->params['pcsApi']['asset']['upload']['minSize'], 'maxSize' => Yii::$app->params['pcsApi']['asset']['upload']['maxSize'], 'maxFiles' => Yii::$app->params['pcsApi']['asset']['upload']['maxFiles']],
];
}
11. List of file extensions that can be uploaded: ogg, pdf, xml, zip, gz, mp4, mp3, wav, webm, gif, jpeg, jpg, png, webp, SVG, SVGZ, TIFF, CSS, CSV, TXT, VCF, VCARD, MOV, QT, MKV, MK3D, MKA, MKS, WMV, FLV, DOC, docx, xls, xlsx, ppt, pptx. List of MIME types that can be uploaded: application/ogg, application/pdf, application/xml, application/zip, application/gzip, audio/mp4, audio/mpeg, audio/ogg, audio/vnd.wave, audio/webm, image/gif, image/jpeg, image/png, image/webp, image/svg+xml, image/tiff, text/css, text/csv, text/plain, text/vcard, text/xml, video/mpeg, video/mp4, video/ogg, video/quicktime, video/webm, video/x-matroska, video/x-ms-wmv, video/x-flv, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation. Upload respectively: docx, xlsx, pptx, all uploaded successfully, in line with expectations, as shown in Figure 6
{
"code": 10000,
"message": "上传资源成功",
"data": {
"items": [
{
"original_file_name": "原始凭证单据(1).docx",
"relative_path": "/tmp/2019/12/20/1576825976.9466.2119963527.docx",
"url": "http://127.0.0.1/pcs-api/storage/tmp/2019/12/20/1576825976.9466.2119963527.docx"
}
]
}
}
{
"code": 10000,
"message": "上传资源成功",
"data": {
"items": [
{
"original_file_name": "周报模板.xlsx",
"relative_path": "/tmp/2019/12/20/1576826044.1977.1865556442.xlsx",
"url": "http://127.0.0.1/pcs-api/storage/tmp/2019/12/20/1576826044.1977.1865556442.xlsx"
}
]
}
}
{
"code": 10000,
"message": "上传资源成功",
"data": {
"items": [
{
"original_file_name": "邮箱使用说明.pptx",
"relative_path": "/tmp/2019/12/20/1576826075.8429.300942829.pptx",
"url": "http://127.0.0.1/pcs-api/storage/tmp/2019/12/20/1576826075.8429.300942829.pptx"
}
]
}
}





