php 52 lines · 7 steps

Detecting file types by MIME in PHP

A small class that reads a file's real MIME type and maps it to a safe, whitelisted extension.

Explained by highlit
1<?php
2 
3namespace App\Support;
4 
5use RuntimeException;
6 
7final class FileTypeDetector
8{
9 private const ALLOWED = [
10 'image/jpeg' => 'jpg',
11 'image/png' => 'png',
12 'image/gif' => 'gif',
13 'image/webp' => 'webp',
14 'application/pdf' => 'pdf',
15 ];
16 
17 public function detect(string $path): string
18 {
19 if (!is_readable($path)) {
20 throw new RuntimeException("Cannot read file: {$path}");
21 }
22 
23 $finfo = new \finfo(FILEINFO_MIME_TYPE);
24 $mime = $finfo->file($path);
25 
26 if ($mime === false) {
27 throw new RuntimeException('Unable to determine MIME type.');
28 }
29 
30 return $mime;
31 }
32 
33 public function guessExtension(string $path): string
34 {
35 $mime = $this->detect($path);
36 
37 if (!isset(self::ALLOWED[$mime])) {
38 throw new RuntimeException("Unsupported file type: {$mime}");
39 }
40 
41 return self::ALLOWED[$mime];
42 }
43 
44 public function isAllowed(string $path): bool
45 {
46 try {
47 return isset(self::ALLOWED[$this->detect($path)]);
48 } catch (RuntimeException) {
49 return false;
50 }
51 }
52}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Inspecting real file contents with finfo beats trusting a client-supplied filename or extension.
  2. 2A whitelist that maps MIME types to extensions rejects everything unexpected by default.
  3. 3Layering methods lets one throw for callers who want detail while another swallows errors for a simple boolean.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Detecting file types by MIME in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code