4

How can a Url object be created from a file URI? Using the URI for a public file as a parameter for Url::fromUri() gives this error.

UnexpectedValueException: External URLs do not have internal route parameters. in Drupal\Core\Url->getRouteParameters().

$file = File::load($file_id);
$file_uri = $file->getFileUri();
$menu_link['url'] = Url::fromUri($file_uri);

Here is the class and method in question: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/function/Url%3A%3AfromUri/8.2.x

Note that I don't need to get the actual URL in string format, I need to generate a Url object from the Url class that points to a file. This is because I am attempting to modify the path of a menu link and unfortunately that is not a simple matter of providing a URL string in Drupal 8.

This is the code I am using.

function teeprop_preprocess_menu__main(&$vars) {
  foreach($vars['items'] as $key => $menu_link) {
    if (!empty($menu_link['url']->getRouteParameters())) {
      $node_id = $menu_link['url']->getRouteParameters()['node'];
      $node_entity = Node::load($node_id);
      $node_type = $node_entity->getType();

      if ($node_type == 'pdf') {
        $file_id = $node_entity->get('field_pdf_file')->getValue()[0]['target_id'];
        $file = File::load($file_id);
//         $file_url = $file->url();
        $file_uri = $file->getFileUri();
        $vars['items'][$key]['url'] = Url::fromUri($file_uri, ['absolute' => TRUE]);
      }
    }
  }
}
  • I'm not sure if this will work for menu link URLs, but I think that external URLs are supported. This could be done by doing $menu_link['url'] = Url::fromUri($file_uri, ['absolute' => TRUE]);. I'm not confident in this, but I use this in freelinking module to send file URIs to Link render element's #uri property. – mradcliffe Sep 26 '17 at 22:06
  • Thank you for the suggestion. Unfortunately that causes the same error. I can't believe how difficult this is. – maskedjellybean Sep 26 '17 at 22:28
  • file_create_url($file->getFileUri() should create an absolute path which should then work with fromUri(). – Berdir Sep 26 '17 at 23:11
  • That also fails with the same error. I wonder why is the Url being interpreted as external? – maskedjellybean Sep 27 '17 at 4:14
  • Can you POST file URI here.. – Ajay Reddy Sep 27 '17 at 6:21
1

I believe that the following should do what you need:

Url::fromUri(
  File::load(1)->url()
);

(I've tested this in a local 8.4.2 installation, and it yields a Url object that can be rendered without an error.)

The functions are admittedly named very misleadingly. Even though ::fromUri() sounds like it should accept the return value of ::getFileUri(), namely public://..., it actually only accepts internal:, base:, entity: and "external" URLs.

So you need to use ->url() to get the external URL of the file, and then pass that to ::fromUri().

  • Be careful if you use ->isExternal(), it will consider your internal file as external file. – Christophe CARON May 15 at 14:05
  • @ChristopheCARON yes, this is another example of the terminology being ambiguous/misleading. "External" seemingly refers to all URLs that aren't either Drupal routes or Drupal system files - the public filesystem is considered "external". – Christoph Burschka May 16 at 9:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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