2 回答

TA貢獻1793條經驗 獲得超6個贊
docx是 Microsoft Word Open XML 格式文檔,它是一種基于 XML 的文件,所有內容都存儲為單獨的文件,并最終壓縮為一個 ZIP 壓縮文件。它看起來像一個文件容器。
并且我們不應該將文件擴展名與 mimetype 相同。據了解,具有docx文件擴展名的正常(帶有 docx 的 mp4 文件不應視為正常)文件可以具有這些 mimetypes 之一。
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
'application/zip'
'application/CDFV2'
在您的代碼中,
$file->getClientOriginalExtension() extract extension from the original file name that was uploaded which should not be considered as a safe value.
$file->getClientMimeType() extract the mime type from client request which should not be considered as a safe value.
Both these two functin implemented in ./vendor/symfony/http-foundation/File/UploadedFile.php
Then take a look at last function in your code,
$file->extension() use some method to guess (which maybe not accurate) the file extension. In sequence php's finfo (manual) which base on the file content, the system file. As the below source code it's guess, so it's not accurate all the time. Refer to file command apparently returning wrong MIME type.
Here you should get it. If you want to go further, see below source code of the function extension.
Source Code
extension call guessExtension to guess the file extension, and guessExtension use the mimetype returned by guessMiMeType
// FileHelpers.php
public function extension()
{
return $this->guessExtension();
}
// File.php
public function guessExtension()
{
return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null;
}
...
public function getMimeType()
{
return MimeTypes::getDefault()->guessMimeType($this->getPathname());
}
guessMiMeType use two guesser to guess the mimetype. php's finfo and system's file, and finfo take high priority than file.
//MimeTypes.php
public function __construct(array $map = [])
{
foreach ($map as $mimeType => $extensions) {
$this->extensions[$mimeType] = $extensions;
foreach ($extensions as $extension) {
$this->mimeTypes[$extension] = $mimeType;
}
}
$this->registerGuesser(new FileBinaryMimeTypeGuesser());
$this->registerGuesser(new FileinfoMimeTypeGuesser());
}
...
/**
* Registers a MIME type guesser.
*
* The last registered guesser has precedence over the other ones.
*/
public function registerGuesser(MimeTypeGuesserInterface $guesser)
{
array_unshift($this->guessers, $guesser);
}
...
public function guessMimeType(string $path): ?string
{
foreach ($this->guessers as $guesser) {
if (!$guesser->isGuesserSupported()) {
continue;
}
if (null !== $mimeType = $guesser->guessMimeType($path)) {
return $mimeType;
}
}
if (!$this->isGuesserSupported()) {
throw new LogicException('Unable to guess the MIME type as no guessers are available (have you enable the php_fileinfo extension?).');
}
return null;
}
//FileinfoMimeTypeGuesser.php
public function guessMimeType(string $path): ?string
{
if (!is_file($path) || !is_readable($path)) {
throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
}
if (!$this->isGuesserSupported()) {
throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
}
if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) {
return null;
}
return $finfo->file($path);
}
//FileBianryMimeTypeGuesser.php
public function __construct(string $cmd = 'file -b --mime %s 2>/dev/null')
{
$this->cmd = $cmd;
}
public function guessMimeType(string $path): ?string
{
if (!is_file($path) || !is_readable($path)) {
throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
}
if (!$this->isGuesserSupported()) {
throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
}
ob_start();
// need to use --mime instead of -i. see #6641
passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
if ($return > 0) {
ob_end_clean();
return null;
}
$type = trim(ob_get_clean());
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
// it's not a type, but an error message
return null;
}
return $match[1];
}
- 2 回答
- 0 關注
- 756 瀏覽
添加回答
舉報