亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Laravel:表單文件上傳失敗 - 檢測到錯誤類型

Laravel:表單文件上傳失敗 - 檢測到錯誤類型

PHP
飲歌長嘯 2021-11-05 18:39:00
我最近使用了一個上傳簡歷的系統,我收到了異常高的拒絕數量,大約 15%。當我查看日志時,它顯示了以下結果:客戶端報告的擴展名是docx(基于$file->getClientOriginalExtension())客戶端報告的 MIME 類型是application/vnd.openxmlformats-officedocument.wordprocessingml.document(基于$file->getClientMimeType())Laravel/PHP 檢測到文件是.bin(基于$file->extension())換句話說,客戶端說它正在上傳一個 docx 文件,但服務器說它收到了一個 bin。起初我以為這只是腐敗,但它經常發生。到目前為止,我只在日志中捕獲了一些,但我注意到每次 Safari 都是瀏覽器。Safari 是否存在任何系統性問題?如果是這樣,我該如何繞過它們?還有什么可能導致問題?我正在使用 Vue 觸發表單提交,但我看不出這有什么不同。這是Vue代碼:document.getElementById("new-application").submit();
查看完整描述

2 回答

?
米脂

TA貢獻1836條經驗 獲得超3個贊

問題在于 PHP 使用file來自操作系統(在本例中為 Ubuntu)的命令根據文件內容猜測擴展名。它弄錯了。升級 Ubuntu 可能會有所幫助。


查看完整回答
反對 回復 2021-11-05
?
搖曳的薔薇

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];

}


查看完整回答
反對 回復 2021-11-05
  • 2 回答
  • 0 關注
  • 756 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號