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
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Inspecting real file contents with finfo beats trusting a client-supplied filename or extension.
- 2A whitelist that maps MIME types to extensions rejects everything unexpected by default.
- 3Layering methods lets one throw for callers who want detail while another swallows errors for a simple boolean.
Related explainers
php
<?php class NameParser {
Parsing a full name into components in PHP
string-parsing
arrays
normalization
Intermediate
8 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
php
<?php namespace App\Services;
Building a cached daily leaderboard in Laravel
caching
aggregation
eager-loading
Intermediate
9 steps
php
<?php final class RotatingFileLogger {
How a rotating file logger works in PHP
logging
file-rotation
io
Intermediate
9 steps
php
class TwoFactorController extends Controller { public function show(Request $request): View|RedirectResponse {
Two-factor auth challenge flow in Laravel
authentication
two-factor
middleware
Intermediate
10 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/detecting-file-types-by-mime-in-php-explained-php-c5ac/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.