我最近启用了上传简历的系统,但拒绝率却异常高,大约为15%。当我查看日志时,它显示了以下结果:
docx
(基于$file->getClientOriginalExtension()
)application/vnd.openxmlformats-officedocument.wordprocessingml.document
(基于$file->getClientMimeType()
).bin
(基于$file->extension()
)换句话说,客户端说它正在上传docx文件,但是服务器说它接收到一个bin。起初我以为这只是腐败,但它经常发生。
到目前为止,我仅在日志中捕获了一些日志,但是我注意到每次Safari浏览器都是浏览器。 Safari是否存在系统性问题?如果是这样,我该如何解决?
还有什么可能导致此问题?
我正在用Vue触发表单提交,但是我看不出这有什么用。这是Vue代码:
document.getElementById("new-application").submit();
答案 0 :(得分:5)
问题是PHP使用OS(在本例中为Ubuntu)中的file
命令来根据文件内容猜测扩展名。错了。升级Ubuntu可能会有所帮助。
答案 1 :(得分:2)
Safari以其mime类型而闻名,这是不正确的。我确定在您的情况下,它不会发送应有的docx哑剧,而是说它是octet-stream
。好吧,您唯一的解决方法是(如果您的文件未损坏)手动设置文件扩展名以更正一个扩展名或从浏览器手动发送文件,确保MIME正确。
答案 2 :(得分:2)
docx
是Microsoft Word Open XML格式文档,基于XML,所有内容都存储为单独的文件,最终压缩为一个ZIP压缩文件。好像是一个文件容器。
我们不应该将文件扩展名与mimetype一样。据了解,扩展名为docx
的普通文件(带有docx的mp4文件不应视为普通文件)可以具有这些模仿类型之一。
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
'application/zip'
'application/CDFV2'
在您的代码中
$file->getClientOriginalExtension()
从上传的原始文件名中提取扩展名,不应将其视为安全值。
$file->getClientMimeType()
从客户端请求中提取哑剧类型,不应将其视为安全值。
这两个函数都在./vendor/symfony/http-foundation/File/UploadedFile.php
中实现
然后看一下代码中的最后一个函数
$file->extension()
使用某种方法来猜测(可能不准确) 。根据文件内容,系统依次为php的finfo
(manual)file
。如下面的源代码所示,因此并非总是准确的。请参阅file command apparently returning wrong MIME type。
在这里您应该得到它 。如果要进一步操作,请参见下面的函数extension
的源代码。
源代码
extension
调用guessExtension
来猜测文件扩展名,并且guessExtension
使用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
使用两个猜测器来猜测模仿类型。 php的finfo
和系统的file
,以及finfo
的优先级比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];
}