I want to ship a default image in my custom module. I know I can reference images in the files directory with public://, but how can I properly reference my module's URL path?

Update: I need to pass this URI to image_style so a raw path to the module directory won't be enough:

  $render_image = [
    '#theme' => 'image_style',
    '#style_name' => 'blah',
    '#uri' => $uri,
  • Get the relative path to your module using the module manager service.
    – Eyal
    Jun 6, 2016 at 21:29

4 Answers 4


Drupal needs a URI (not just a URL or filepath) to generate an image style derivative. All URIs begin with a stream wrapper like "public://" or "private://". The stream wrapper tells Drupal how to handle the resource; for example, "public" typically means "treat this resource as a local file within sites/default/files."

You won't be able to use the "public" stream wrapper for assets in a module directory, because that module does not live in sites/default/files.

Drupal doesn't come with a stream wrapper for module or theme assets, but there's a contributed module to add that functionality at https://www.drupal.org/project/system_stream_wrapper.


The value passed as #uri can be either the image URI or an image relative path. template_preprocess_image_style() passes the value of $variables['uri'] to ImageStyle::buildUrl() which as first parameter accepts either the image relative path or its URI.

  $style = ImageStyle::load($variables['style_name']);

  // Determine the dimensions of the styled image.
  $dimensions = [
    'width' => $variables['width'],
    'height' => $variables['height'],
  $style->transformDimensions($dimensions, $variables['uri']);
  $variables['image'] = [
    '#theme' => 'image',
    '#width' => $dimensions['width'],
    '#height' => $dimensions['height'],
    '#attributes' => $variables['attributes'],
    '#style_name' => $variables['style_name'],

  // If the current image toolkit supports this file type, prepare the URI for
  // the derivative image. If not, just use the original image resized to the
  // dimensions specified by the style.
  if ($style->supportsUri($variables['uri'])) {
    $variables['image']['#uri'] = $style->buildUrl($variables['uri']);

To get the module path, both drupal_get_path('module', $module_name), which is still implemented even in Drupal 9.3.x, and \Drupal::moduleHandler()->getModule($module_name)->getPath() return the same value. Deprecate drupal_get_path() and drupal_get_filename() and replace with ExtensionList::getPath() and ExtensionList::getPathname() and drupal_get_path() and drupal_get_filename() have been deprecated in favor of extension listing services (the associated change record) suggest to use either \Drupal::service('extension.list.module')->getPath($module_name) or \Drupal::service('extension.path.resolver')->getPath('module', $module_name), to get a module path.


The \Drupal class has many useful static functions such as moduleHandler. I recommend (for future issues) to first search there, then in the core.services.yml & system.services.yml files for a service or a method that could help.


I think following is easy method to do this

Create private file path

$settings['file_private_path'] = 'give path to you /private-files'; \Drupal::service('file_system')->realpath("private://");

Now you can use this to upload your module related file also custom file for custom form.

Ref: https://www.drupal.org/docs/8/modules/skilling/installation/set-up-a-private-file-path

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.