I had a similiar scenario, and needed to get the URL of an image to use for the CSS for a background image for the whole page, except I was using a media entity instead of a file entity. I thought it might be useful to note it here. I also wanted to use the original image URL instead of a particular style. I used a modified version of the first answer:
use Drupal\file\Entity\File;
// Get media file path to add to template variables to use as background image in template
function mytheme_preprocess_page(&$variables, $hook) {
if (isset($variables['node'])) {
$node = $variables['node'];
if($node->field_image_media[0]){
$media_entity = $node->field_image_media[0]->entity;
$file_id = $media_entity->getSource()->getSourceFieldValue($media_entity);
$bg_file = File::load($file_id);
$path = $bg_file->createFileUrl();
$variables['bg_image'] = $path;
}
}
}
The difference is after returning the media entity, I then needed an extra step to get the entity for the file, before returning the file URL. (Thanks to Akhilavnair's comment in the How to get image file uri from media entity id thread, in showing how to retrieve the File entity from the media entity)
As this is a page preprocess function the variable was not available for the html.html.twig template, and only for the page.html.twig template. This meant to get the background image to apply to the whole page I needed to wrap the <header>
, <main>
and <footer>
html elements in a <div>
and apply the style to that wrapper <div>
.
To retrieve the path and apply the styling I added the following to my page.html.twig:
{% if bg_image is defined %}
{% set bg_style = "background-image:url('" ~ bg_image ~ "'); background-size: cover;" %}
{% endif %}
<div class="box-wrapper" style="{{ bg_style }}">
<header>
...
</header>
<main>
...
</main>
<footer>
...
</footer>
</div>
The image I am retrieving from the media field can also be used within the manage display form as normal using any of the available image styles, or it can hidden (as in my case). And voila: