src/EventListener/AttachmentPreviewListener.php line 31

Open in your IDE?
  1. <?php
  2. namespace App\EventListener;
  3. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  4. use Symfony\Component\HttpKernel\KernelEvents;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\HttpFoundation\StreamedResponse;
  7. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  8. use Psr\Log\LoggerInterface;
  9. /**
  10. * Event listener to serve image attachments inline (preview) instead of forcing download
  11. */
  12. class AttachmentPreviewListener implements EventSubscriberInterface
  13. {
  14. private $logger;
  15. public function __construct(LoggerInterface $logger)
  16. {
  17. $this->logger = $logger;
  18. }
  19. public static function getSubscribedEvents()
  20. {
  21. return [
  22. KernelEvents::RESPONSE => ['onKernelResponse', 10],
  23. ];
  24. }
  25. public function onKernelResponse(ResponseEvent $event)
  26. {
  27. $request = $event->getRequest();
  28. $response = $event->getResponse();
  29. // Only process attachment download responses
  30. if (!$request->attributes->has('attachmentId')) {
  31. return;
  32. }
  33. // Only process StreamedResponse (UVDesk's download response)
  34. if (!($response instanceof StreamedResponse)) {
  35. return;
  36. }
  37. // Check if Content-Disposition header exists and is set to attachment
  38. $contentDisposition = $response->headers->get('Content-Disposition');
  39. if (!$contentDisposition || strpos($contentDisposition, 'attachment') === false) {
  40. return;
  41. }
  42. // Get content type
  43. $contentType = $response->headers->get('Content-Type');
  44. // Check if it's an image
  45. $isImage = $contentType && in_array($contentType, [
  46. 'image/jpeg',
  47. 'image/jpg',
  48. 'image/png',
  49. 'image/gif',
  50. 'image/webp',
  51. 'image/svg+xml',
  52. ]);
  53. if ($isImage) {
  54. // Change Content-Disposition from attachment to inline for images
  55. $filename = '';
  56. if (preg_match('/filename="([^"]+)"/', $contentDisposition, $matches)) {
  57. $filename = $matches[1];
  58. }
  59. $response->headers->set('Content-Disposition', 'inline; filename="' . $filename . '"');
  60. $this->logger->debug('Changed attachment response to inline for image', [
  61. 'attachment_id' => $request->attributes->get('attachmentId'),
  62. 'content_type' => $contentType,
  63. ]);
  64. }
  65. }
  66. }