Magento 2 can not upload product images

Solved
This error can be caused by several server configuration issues. Each error will always present itself with the same generic warning from Magento 2: Attention: We don't recognize or support this file extension type. If your using Magento 2.2.0+ the error may be worded differently. Below are the most common server settings that are causing this error. There may be more than this list but these are all I have personally tested.

1) Permission Problem
You may get an error along the lines of "Can not create directory pub/media/tmp" or you may notice after examining the XHR summary in developer tools that a 200 success code is returned but no data was saved to the server. The easiest way to test this to check your servers permissions and make sure all the directories, especially everything under pub/media is 755. You may have a mix of the following issues as well so do not stop troubleshooting permissions until you check them as well.

2) Missing Write Permissions to Upload Directory / Missing Directory
PHP needs to use the servers temporary upload directory when uploading files to the server. Make sure that your server has a temporary upload directory setup and is writable by the Magento user; whichever user you are using for your Magento website. Most hosting providers have this setup for you but some may lock down this feature or may be missing a default setting. Private servers sometimes rely on you choosing the temporary upload directory per domain and then defaulting to a generic location if you failed to choose one. Look in your php.ini (phpinfo) for upload_tmp_dir. No value means the server will use the default if it can find any.

3) Insufficient max file size and post file size
In your php.ini file you need to correctly set your upload_max_filesize and post_max_size. If any image or any upload of images exceeds these settings you will get the error from the OP. Remember this rule:

post_max_size must be >= upload_max_filesize

Also note that your web host will most likely not warn you if you entered an incorrect value here. You could mistype the value or choose a size the web host does not allow. Test for this.

4) PHP GD (image processing) extension missing
You should have been warned during install if you were missing this extension but PHP upgrades on your server could have disabled it. The fastest way to check this setting is to look through the print out of phpinfo() but you can look it up in cPanel or your Apache/PHP provisioning on an Apache server.

5) PHP ImageMagick (image processing) extension missing
Starting with Magento 2.2.0+ Magento would like to use ImageMagick as well. The documentation is not to clear but it appears you can use one or both of these PHP extensions. If you upgrade to or install PHP 7+ on your server there is a chance it will disable GB and enable ImageMagick depending on how your provisioning your server. Just check that one if not both of them is enabled and working correctly.

Test Script
The following is a PHP script you can use to test for some of these issues. Make a simple HTML form with one file input field named upfile and set the form action to submit to wherever you place this script on your server. You will need to create an uploads directory in the same directory as this script. It is not my code, it was originally posted to the PHP Manual by CertaiN.

<?php

header('Content-Type: text/plain; charset=utf-8');

try {

// Undefined | Multiple Files | $_FILES Corruption Attack
// If this request falls under any of them, treat it invalid.
if (
    !isset($_FILES['upfile']['error']) ||
    is_array($_FILES['upfile']['error'])
) {
    throw new RuntimeException('Invalid parameters.');
}

// Check $_FILES['upfile']['error'] value.
switch ($_FILES['upfile']['error']) {
    case UPLOAD_ERR_OK:
        break;
    case UPLOAD_ERR_NO_FILE:
        throw new RuntimeException('No file sent.');
    case UPLOAD_ERR_INI_SIZE:
    case UPLOAD_ERR_FORM_SIZE:
        throw new RuntimeException('Exceeded filesize limit.');
    default:
        throw new RuntimeException('Unknown errors.');
}

// You should also check filesize here. 
if ($_FILES['upfile']['size'] > 1000000) {
    throw new RuntimeException('Exceeded filesize limit.');
}

// DO NOT TRUST $_FILES['upfile']['mime'] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
    $finfo->file($_FILES['upfile']['tmp_name']),
    array(
        'jpg' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
    ),
    true
)) {
    throw new RuntimeException('Invalid file format.');
}

// You should name it uniquely.
// DO NOT USE $_FILES['upfile']['name'] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
if (!move_uploaded_file(
    $_FILES['upfile']['tmp_name'],
    sprintf('./uploads/%s.%s',
        sha1_file($_FILES['upfile']['tmp_name']),
        $ext
    )
)) {
    throw new RuntimeException('Failed to move uploaded file.');
}

echo 'File is uploaded successfully.';

} catch (RuntimeException $e) {

echo $e->getMessage();

}

?>

In my case, I need to enable fileinfo extension for PHP to make it work. If I disable fileinfo extension, it will generate this error again. I m using php 7.2, Magento 2.3.3 community version.


I fixed it in cPanel > PHP Selector extensions when I had the same error:

  1. Select gd
  2. Select xsl

Then I tried to upload images again and this error is not there anymore.

enter image description here