How do I create a Url object from the public file URI? 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-&gt;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(&amp;$vars) {
  foreach($vars['items'] as $key =&gt; $menu_link) {
    if (!empty($menu_link['url']-&gt;getRouteParameters())) {
      $node_id = $menu_link['url']-&gt;getRouteParameters()['node'];
      $node_entity = Node::load($node_id);
      $node_type = $node_entity-&gt;getType();

      if ($node_type == 'pdf') {
        $file_id = $node_entity-&gt;get('field_pdf_file')-&gt;getValue()[0]['target_id'];
        $file = File::load($file_id);
//         $file_url = $file-&gt;url();
        $file_uri = $file-&gt;getFileUri();
        $vars['items'][$key]['url'] = Url::fromUri($file_uri, ['absolute' =&gt; TRUE]);
      }
    }
  }
}
I believe that the following should do what you need:

Url::fromUri(
  File::load(1)-&gt;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 -&gt;url() to get the external URL of the file, and then pass that to ::fromUri().