This bug for IE and maybe some other browsers is happening because of 2 reasons:
Header always set X-Content-Type-Options nosniff
in root .htaccess- Sometimes uploaded images files have a mime type not corresponding to the file extension
So to easily fix this issue you could remove the Header always set X-Content-Type-Options nosniff
from the root .htaccess file but doing so would lead to some security vulnerabilities.
The second option would be to change the image file extension to reflect the mime type but it could be time consuming to make editors check the rendered output of each image on a big variety of browsers.
A third solution would be to validate the mime type and file extension in files fields, wysiwyg editors and any other way to upload an image file.
My solution in the meanwhile worth to be shared I think and is to create a module with a KernelEvents::RESPONSE
subscriber to modify the file's header:
Here is how I have done:
Create a my_module.services.yml and put this code:
services:
my_module.fix_header:
class: '\Drupal\my_module\Subscriber\MyModuleModifyHeaders'
tags:
- { name: 'event_subscriber' }
Create a folder 'src' in your module and a folder 'Subscriber' into this 'src' folder.
Create a 'MyModuleModifyHeaders.php' file into 'my_module/src/Subscriber/' and write this code in it :
namespace Drupal\my_module\Subscriber;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MyModuleModifyHeaders implements EventSubscriberInterface {
public function __construct() {
}
/**
* Modify headers.
*/
public function onRespond(FilterResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$response = $event->getResponse();
if(\Drupal::request()->query->has('file') && $response->headers->has('Content-Type') && in_array($response->headers->get('Content-Type'), ['image/png', 'image/jpeg', 'image/gif', 'image/bmp', 'image/vnd.microsoft.icon', 'image/tiff'])) {
$target = \Drupal::request()->query->get('file');
$image_uri = 'public://' . $target;
$realPath = \Drupal::service('file_system')->realpath($image_uri);
if (!file_exists($realPath)) {
$image_uri = 'private://' . $target;
$realPath = \Drupal::service('file_system')->realpath($image_uri);
if (!file_exists($realPath)) {
$realPath = null;
}
}
if($realPath) {
$mime_type = '';
$imageData = @getimagesize($realPath);
if (!empty($imageData['mime'])) {
$mime_type = $imageData['mime'];
}
if($response->headers->get('Content-Type') != $mime_type && in_array($mime_type, ['image/png', 'image/jpeg', 'image/gif', 'image/bmp', 'image/vnd.microsoft.icon', 'image/tiff'])) {
//if ($response->headers->has('X-Content-Type-Options')) {
// $response->headers->remove('X-Content-Type-Options');
//}
$response->headers->remove('Content-Type');
$response->headers->set('Content-Type', $mime_type);
}
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = ['onRespond', -100];
return $events;
}
}
You can notice that I am modifying the header only in case of an image file with the wrong extension.
I am not sure though this is the right way to share this solution. Sorry if it is not or if you think this is not the right way to proceed. I am open to any other solution.