File renderers for the file abstraction layer (FAL) 

A file renderer returns the HTML output for a file that is no image, for example the HTML tag <video> for a video file. The ViewHelper <f:media> uses the first file renderer that can render the file, and renders the file as an image if there is none.

TYPO3 Core ships file renderers for audio files, video files, and the online media of YouTube and Vimeo. Extensions can add file renderers for other file types.

Register a file renderer with #[AsFileRenderer] 

Changed in version 15.0 Breaking: #110277 - File renderer registration and interface changed

File renderers are registered as services. A registration with RendererRegistry->registerRendererClass() in ext_localconf.php has no effect anymore. The method getPriority() was removed from FileRendererInterface , and the remaining methods are now strictly typed. To support TYPO3 v14 as well, keep the registration in ext_localconf.php and the method getPriority() , add the attribute, and leave the parameters $width and $height untyped.

A file renderer implements FileRendererInterface and is registered with the PHP attribute AsFileRenderer . This renderer embeds PDF files in an <iframe> :

EXT:my_extension/Classes/Resource/Rendering/PdfRenderer.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Resource\Rendering;

use TYPO3\CMS\Core\Attribute\AsFileRenderer;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\Rendering\FileRendererInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

#[AsFileRenderer(priority: 10)]
final readonly class PdfRenderer implements FileRendererInterface
{
  public function canRender(FileInterface $file): bool
  {
    return $file->getMimeType() === 'application/pdf';
  }

  public function render(
    FileInterface $file,
    int|string $width,
    int|string $height,
    array $options = [],
  ): string {
    // Width and height can carry a suffix like "m" or "c", the iframe
    // takes the number only. An empty value leaves out the attribute.
    $attributes = [
      'src' => $file->getPublicUrl(),
      'title' => $options['title'] ?? $file->getName(),
      'width' => (int)$width ?: null,
      'height' => (int)$height ?: null,
    ];
    return '<iframe ' . GeneralUtility::implodeAttributes($attributes, true)
      . '></iframe>';
  }
}
Copied!
Method canRender()
Return true if the renderer can render the given file or file reference.
Method render()
Return the HTML output for the file. $width and $height are numbers or numbers with a suffix like 200m or 200c, as in the width property of imgResource. $options contains the arguments of the ViewHelper <f:media> and the values of its argument additionalConfig.

A file renderer is a service, so it can use dependency injection in its constructor.

Priority of file renderers 

TYPO3 asks the file renderers in the order of their priority, the highest first. The first renderer that can render the file renders it. The renderers of TYPO3 Core have the priority 0, so a renderer with a higher priority takes precedence, for example to replace the video renderer. Give a renderer a negative priority to ask it only after the renderers of TYPO3 Core. The order of renderers with the same priority is not defined. Give each renderer its own priority if the order matters.

Register a file renderer with the service tag fal.file_renderer 

Instead of the attribute, the service tag fal.file_renderer can be used:

EXT:my_extension/Configuration/Services.yaml
services:
  # Place here the default dependency injection configuration

  MyVendor\MyExtension\Resource\Rendering\PdfRenderer:
    tags:
      - name: fal.file_renderer
        priority: 10
Copied!

Render a file with the ViewHelper <f:media> 

The ViewHelper <f:media> renders each file with the file renderer that can render it. With the example renderer, PDF files are embedded in an <iframe> , and images are still rendered as images:

EXT:my_extension/Resources/Private/Templates/Downloads.fluid.html
<f:for each="{files}" as="file">
    <f:media file="{file}" width="800" height="600" title="{file.title}" />
</f:for>
Copied!

The argument title reaches the renderer in $options. If a file has no title, the example renderer uses the file name.