With managed file, dynamically set fileName and #upload_location
Thanks @Clive. I just read your comment, but in the mean time I found the answer myself. This is the essentials of my code in my submitForm() method. It still seems a bit hacky to me but it works.
$images = $form_state-&gt;getValue('images');
$file = File::load( $images[0] );

$file-&gt;setPermanent();
$file-&gt;save();

$new_filename = &quot;photos/test/test-02.jpg&quot;;
$stream_wrapper = \Drupal::service('file_system')-&gt;uriScheme($file-&gt;getFileUri());
$new_filename_uri = &quot;{$stream_wrapper}://{$new_filename}&quot;;

file_move($file, $new_filename_uri); // &lt;===== The essential line!

$file = File::load( $images[0] );
dpm($file-&gt;getFilename()); // returns test-02.jpg
dpm($file-&gt;getFileUri());  // returns public://photos/test/test-02.jpg