LoginSignup
4
3

More than 3 years have passed since last update.

【Laravel】getMimeTypeとgetClientMimeTypeの違いと取得できる値の比較

Last updated at Posted at 2021-02-23

はじめに

 この記事では、getMimeTypeとgetClientMimeTypeのそれぞれの定義と取得できる値の違いをまとめました。

「あれ、このファイルをアップロードした時にどんな値がとれるんだっけ?」

って時にさっと確認できるように比較表を記載してますので、結果だけ知りたい場合は結果の比較表をご覧ください。

背景

 Laravelを利用したWEBアプリケーションを開発中に、ユーザーがアップロードした画像に対してMIMEタイプ別に加工処理をする必要が出てきたのがきっかけです。

調べたところ、getMimeTypeとgetClientMimeTypeの2つがあり、どちらを使うのが正しいのか、それぞれ取得できる値に違いがあるのか気になったので、まとめてみやすいようにしてみました。

 また個人的な理由ですが、いままで「仕事が忙しい」を言い訳にいっさいアウトプットをしてこなかったため、今年こそはと一念発起して書き始めました。備忘録兼自分の理解を深める目的で書いてますので、内容に間違いがあったり、もっといいやり方や別のやり方等がありましたら、コメントいただけると嬉しいです!

環境

(Docker上でPHPの実行環境を作って試しています。)
Debian GNU/Linux: 10.6
PHP: 7.4.12
Laravel Framework: 8.13.0

getMimeTypeとgetClientMimeTypeについて

定義

getMimeType()

route_folder/vendor/symfony/http-foundation/Request.php

<?php

namespace Symfony\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

/* 〜〜〜〜省略〜〜〜〜〜 */

class Request
{
    /* 〜〜〜〜省略〜〜〜〜〜 */

    /**
     * Gets the mime type associated with the format.
     *
     * @return string|null The associated mime type (null if not found)
     */
    public function getMimeType(string $format)
    {
        if (null === static::$formats) {
            static::initializeFormats();
        }

        return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
    }

    /* 〜〜〜〜省略〜〜〜〜〜 */
}

getClientMimeType()

route_folder/vendor/symfony/http-foundation/File/UploadedFile.php
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\HttpFoundation\File;
    /* 〜〜〜〜省略〜〜〜〜〜 */

/**
 * A file uploaded through a form.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class UploadedFile extends File
{
    /* 〜〜〜〜省略〜〜〜〜〜 */

    /**
     * Returns the file mime type.
     *
     * The client mime type is extracted from the request from which the file
     * was uploaded, so it should not be considered as a safe value.
     *
     * For a trusted mime type, use getMimeType() instead (which guesses the mime
     * type based on the file content).
     *
     * @return string The mime type
     *
     * @see getMimeType()
     */
    public function getClientMimeType()
    {
        return $this->mimeType;
    }

    /* 〜〜〜〜省略〜〜〜〜〜 */
}

違いと使い分け

getClientMimeType()のコメント部分にがっつり記載されてました。

Returns the file mime type.

The client mime type is extracted from the request from which the file
was uploaded, so it should not be considered as a safe value.

For a trusted mime type, use getMimeType() instead (which guesses the mime
type based on the file content).

getClientMimeType()はファイルをアップロードしたリクエストから抽出されたものなので正確なものではなく、信頼できるMIMEタイプを取得したい場合はgetMimeType()を使ってください。とのことでした。

またこちらにも同じような内容の質問で、とても分かりやすい回答が載ってました。
https://stackoverflow.com/questions/39594854/why-does-laravels-getmimetype-method-identify-a-file-as-application-octet-st

こちらのサイトの答えをお借りすると、

getMimeType() -> ファイルの内容をみてMIMEタイプを判断

getClientMimeType() -> ブラウザが判定した情報を元にMIMEタイプを判断

なので、正確にMIMEタイプを撮りたい場合はgetMimeType()を使うと良さそうでした。

ただ、上記の質問者の方のようにmp3をあげたはずなのにgetMimeType()だと別の値になってしまうとのことで、取得できる値を整理してみました。

準備

今回は実際に取得できる値を確認するだけなので、DBへの保存等はせず、ログに吐き出すだけの処理を実装しました。

route_folder/routes/web.php
Route::get('/file/upload', 'LectureController@index');
Route::post('/file/upload', 'LectureController@upload');
route_folder/app/Http/Controllers/FileUploadController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FileUploadController extends Controller
{

    public function index()
    {
        return view('file.upload');
    }

    public function upload(Request $request)
    {
        $images = $request->file('images');
        foreach ($images as $image) {
            logger('拡張子: '.$image->getClientOriginalExtension());
            logger('getMimeType(): '.$image->getMimeType());
            logger('getClientMimeType(): '.$image->getClientMimeType());
        }

        return redirect('/file/upload');
    }


}
route_folder/resources/views/file/upload.blade.php

<div>
    <form action="/file/upload" method="POST" enctype='multipart/form-data'>
        @csrf
        <h2>画像アップロード</h2>
        <div>
            <input type="file" name="images[]" multiple="multiple">
        </div>
        <button type="submit">更新</button>
    </form>
</div>

出力結果

route_folder/storage/logs/laravel-2021-02-23.log
[2021-02-23 12:58:26] stack-channel.DEBUG: 拡張子: pdf  
[2021-02-23 12:58:26] stack-channel.DEBUG: getMimeType(): application/pdf  
[2021-02-23 12:58:26] stack-channel.DEBUG: getClientMimeType(): application/pdf  

結果

基本的にはどちらも取得結果は同じでしたが、

画像系のファイルだとsvg,

テキスト系のファイルだとcsv,txt,log,nfo,srt

動画系のファイルだとwav, aiff

辺りが違ってたので、テキストファイルや動画ファイルあたりを扱うときにはをつけた方が良さそうでした。

拡張子 getMimeType() getClientMimeType()
.jpeg,jpg,jpe,jfif image/jpeg image/jpeg
.png image/png image/png
.gif image/gif image/gif
.HEIC image/heic image/heic
.ai application/postscript application/postscript
.psd image/vnd.adobe.photoshop image/vnd.adobe.photoshop
.tif image/tiff image/tiff
.svg text/html image/svg+xml
.csv text/plain text/csv
.txt text/plain text/plain
.log text/plain application/octet-stream
.nfo text/plain application/octet-stream
.srt text/plain application/octet-stream
.xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.doc application/msword application/msword
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document application/vnd.openxmlformats-officedocument.wordprocessingml.document
.pptx application/vnd.openxmlformats-officedocument.presentationml.presentation application/vnd.openxmlformats-officedocument.presentationml.presentation
.mp3 audio/mpeg audio/mpeg
.mid audio/midi audio/midi
.wav audio/x-wav audio/wav
.aiff audio/x-aiff audio/aiff
.ogg audio/ogg audio/ogg
.mov video/quicktime video/quicktime
.zip application/zip application/zip
.rar application/x-rar application/x-rar

引用

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3