Using Symfony's MimeTypeGuesser to Get Server-Side Mimetypes

Writing this down for the next time I forget

Published on February 3, 2020

Recently, in my work at Clockwise, I ran into a scenario where I needed to figure out the mimetype of an uploaded file. That file had to be run through ImageMagick, and the parameters we passed to that command would vary depending on the file type. Trying to guess the image type based on file extensions was proving unreliable, so we had to find another way.

As it turns out, Symfony’s Mime component has a utility to guess mime types, and since Laravel is built on top of Symfony, there was no additional installation required! Just import the class at the top of your file:


namespace App\Http\Controllers\ImageController;

use Symfony\Component\Mime\MimeTypes;

class ImageController extends Controller
{
}

All you need to do is instantiate the MimeTypes class, and pass the filepath to its guessMimeType() function.


  $mimeTypes = new MimeTypes();
  $mimeType = $mimeTypes->guessMimeType(Storage::disk('public')->path($filePath));

The function will return the file’s mimetype as a string like image/jpeg. In the unlikely event that the guesser cannot determine the file’s mimetype, it will simply return null.

This function provides a super nice wrapper of PHP’s finfo_file function, which is part of the fileinfo extension:


/**
 * Lines 42-62 of Symfony/Component/Mime/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);
}

This guessMimeType function accepts the file path, confirms it’s readable, and then confirms that the PHP installation has the fileinfo extension is installed.

Once confirmed, it creates a new instance of finfo, and passes the FILEINFO_MIME_TYPE constant, which tells the class to return the mimetype of the file in question.

Finally, we pass the file in question to the file() function, and return the file’s mimetype as the result. It’s this string value that gets returned all the way up to our controller—Symfony just wraps it up nicely for us.

Currently Listening: Tim Presley w/ White Fence, "Indisposed"

On Recommendations

Last updated on February 4, 2019

As a developer, I pride myself on being able to explain techy stuff to non-techy folks. In fact, I think it’s one of the most important skills... Read More »