<?php
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Psr\Log\LoggerInterface;
/**
* Event listener to serve image attachments inline (preview) instead of forcing download
*/
class AttachmentPreviewListener implements EventSubscriberInterface
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => ['onKernelResponse', 10],
];
}
public function onKernelResponse(ResponseEvent $event)
{
$request = $event->getRequest();
$response = $event->getResponse();
// Only process attachment download responses
if (!$request->attributes->has('attachmentId')) {
return;
}
// Only process StreamedResponse (UVDesk's download response)
if (!($response instanceof StreamedResponse)) {
return;
}
// Check if Content-Disposition header exists and is set to attachment
$contentDisposition = $response->headers->get('Content-Disposition');
if (!$contentDisposition || strpos($contentDisposition, 'attachment') === false) {
return;
}
// Get content type
$contentType = $response->headers->get('Content-Type');
// Check if it's an image
$isImage = $contentType && in_array($contentType, [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'image/webp',
'image/svg+xml',
]);
if ($isImage) {
// Change Content-Disposition from attachment to inline for images
$filename = '';
if (preg_match('/filename="([^"]+)"/', $contentDisposition, $matches)) {
$filename = $matches[1];
}
$response->headers->set('Content-Disposition', 'inline; filename="' . $filename . '"');
$this->logger->debug('Changed attachment response to inline for image', [
'attachment_id' => $request->attributes->get('attachmentId'),
'content_type' => $contentType,
]);
}
}
}