How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Upload Only Image Files Using PHP
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Web Development > How to Upload Only Image Files Using PHP
Web Development

How to Upload Only Image Files Using PHP

how7o
By how7o
Last updated: May 23, 2026
6 Min Read
Securely upload only image files in PHP
SHARE

To upload only image files using PHP, don’t trust $_FILES['x']['type'] alone — that’s user-controlled. Verify the bytes with getimagesize() (or finfo_file()), check the extension, and configure the upload directory so it can’t execute scripts. Defence in depth is the rule for any user-supplied file.

Contents
  • The minimal version (from the source)
  • Robust version — inspect the bytes
  • Block script execution in the uploads directory
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-05-17 on PHP 8.3. Originally published 2022-11-30, rewritten and updated 2026-05-17.

The minimal version (from the source)

<?php
if ( isset( $_FILES['image_file'] ) && $_FILES['image_file']['error'] === UPLOAD_ERR_OK ) {
    $allowed  = [ 'image/jpeg', 'image/gif', 'image/png', 'image/webp' ];
    $filename = $_FILES['image_file']['name'];

    if ( in_array( $_FILES['image_file']['type'], $allowed, true ) ) {
        $dest = 'upload/' . $filename;
        if ( file_exists( $dest ) ) {
            echo $filename . ' already exists.';
        } else {
            move_uploaded_file( $_FILES['image_file']['tmp_name'], $dest );
            echo 'Your image uploaded successfully.';
        }
    } else {
        echo 'Error: only image files are allowed!';
    }
}

Works — but the MIME-type check ($_FILES['x']['type']) is browser-supplied and trivially spoofed. For anything user-facing, also verify the actual file contents (next section).

PHP image upload — getimagesize byte check, rename on disk, htaccess block PHP execution

Robust version — inspect the bytes

<?php
if ( isset( $_FILES['image_file'] ) && $_FILES['image_file']['error'] === UPLOAD_ERR_OK ) {
    $tmp_path = $_FILES['image_file']['tmp_name'];

    // 1. Verify the file is actually an image by reading its header
    $info = getimagesize( $tmp_path );
    if ( $info === false ) {
        die( 'Not a valid image.' );
    }

    // 2. Whitelist allowed image types by IMAGETYPE_*
    $allowed_types = [ IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_WEBP ];
    if ( ! in_array( $info[2], $allowed_types, true ) ) {
        die( 'This image format is not allowed.' );
    }

    // 3. Generate a safe, server-controlled filename
    $ext       = image_type_to_extension( $info[2] );    // .jpg / .png / .gif / .webp
    $safe_name = bin2hex( random_bytes( 16 ) ) . $ext;
    $dest      = __DIR__ . '/upload/' . $safe_name;

    // 4. Move into place
    if ( move_uploaded_file( $tmp_path, $dest ) ) {
        echo "Uploaded as $safe_name";
    } else {
        die( 'Failed to save the file.' );
    }
}
  • getimagesize() opens the file and returns dimensions + an IMAGETYPE_* constant. Returns false for non-image bytes — the simplest “is this really an image?” check.
  • Whitelist on IMAGETYPE_* instead of MIME or extension. These come from PHP after inspecting the bytes, so the user can’t lie about them.
  • Server-generated filename via random_bytes(16). Drops directory-traversal and overwrite attempts in one step.
  • image_type_to_extension() maps the type constant back to .jpg/.png/etc., so the stored file has the right extension for its actual content.

Block script execution in the uploads directory

# upload/.htaccess (Apache)
<FilesMatch "\.(ph(p[3-7]?|tml))$">
    Require all denied
</FilesMatch>
# /etc/nginx/sites-available/example.com (Nginx)
location /upload/ {
    location ~ \.(ph(p[3-7]?|tml))$ {
        deny all;
    }
}

Even with perfect validation, an attacker who manages to write a .php file to the uploads dir cannot have it executed. This is the “if validation fails, contain the damage” layer.

Frequently asked questions

Why is checking the file extension not enough?

Extensions are trivially renameable. A malicious user can rename shell.php to shell.jpg, upload it, and have it served as PHP if the server is misconfigured. The MIME type from $_FILES['x']['type'] is also user-controlled (the browser sends it). The only reliable check is opening the file and inspecting its bytes — getimagesize() or finfo_file() does this.

What’s wrong with trusting $_FILES['x']['type']?

It’s whatever the user’s browser claims, not what the file actually is. A request can set Content-Type: image/jpeg on any payload. Better path: pass the file to finfo_file (libmagic-backed inspection) or call getimagesize(), which returns false if the bytes aren’t a recognised image format.

How do I block .php, .phtml, etc. from being executed even if uploaded?

Configure the web server. In Apache, place an .htaccess in the uploads directory: <FilesMatch "\.(ph(p[3-7]?|tml))$"> Require all denied </FilesMatch>. In Nginx, add a location ~ \.(ph(p[3-7]?|tml))$ { deny all; } block inside the uploads location. Defence in depth: even if validation fails, execution is blocked.

Should I rename uploaded files?

Yes — generate a server-controlled name (uniqid(), UUID, or hash of the contents) and don’t keep the user’s name. Stops directory-traversal attempts (../../etc/passwd), collision-based overwrites, and information leaks (the user’s filename can contain their real name or PII). Keep the original name in your database if you need it for display.

Related guides

  • How to Upload Files via Ajax with jQuery
  • How to Open a File Dialog When Clicking a Button
  • How to Create a Folder If It Does Not Exist in PHP

References

PHP getimagesize(): php.net/manual/en/function.getimagesize.php. PHP move_uploaded_file(): php.net/manual/en/function.move-uploaded-file.php. PHP finfo_file(): php.net/manual/en/function.finfo-file.php.

TAGGED:filesystemphpSecurity

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Upload files via Ajax with jQuery using FormData How to Upload Files via Ajax with jQuery
Next Article Laravel leftJoin to keep all records even without matches How to Use LEFT JOIN in Laravel to Keep All Records
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Laravel Eloquent ORM — a model class mapping to a database table with query methods
Laravel Eloquent ORM: The Complete Guide to Querying Your Database
June 16, 2026
Set vi as the default editor in Ubuntu — a terminal opening the vim editor
How to Set vi (Vim) as the Default Editor in Ubuntu
June 8, 2026
rsync says ALL DONE but files are missing — a terminal showing ALL DONE next to an empty folder
rsync Says “ALL DONE” but Files Are Missing: How to Verify
June 8, 2026
Migrate a website to a new server with rsync — files copying from an old server to a new one over SSH
How to Migrate a Website to a New Server With rsync
June 8, 2026
Bun runtime — faster JS toolkit replacing npm in Laravel projects
How to Install Bun Runtime on Ubuntu (And Use It in a Laravel Project)
May 24, 2026

You Might Also Like

Create a folder in PHP if it does not already exist
Web Development

How to Create a Folder If It Does Not Exist in PHP

5 Min Read
Laravel last inserted ID — Eloquent save populates model primary key illustration
Web Development

How to Retrieve the Last Inserted ID in Laravel Eloquent

8 Min Read
Laravel left outer join — query builder leftJoin illustration with two tables
Web Development

How to Do a Left Outer Join in Laravel Query Builder

8 Min Read
Get the first character of a PHP string with mb_substr for UTF-8
Web Development

How to Get the First Character of a String in PHP

5 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?