In a form I want to bulk upload jpgs renaming them using exif date information and dynamically setting the #upload_location according to the value of a textfield in the same form.

I have no problem with accessing the exif date information. What I don't know how to do, is dynamically set the file name and file path (actual location on the server) programmatically.

This is my form upload element:

$form['images'] = array(
  '#type' => 'managed_file',
  '#multiple' => TRUE,
  '#upload_validators' => array(
    'file_validate_extensions' => array('jpg'),
  '#upload_location' => 'public://photos',
  '#required' => TRUE,

$form['file'] = [
  '#type' => 'fieldset',
  '#title' => $this->t('File'),

$form['file']['name'] = [
  '#type' => 'textfield',
  '#title' => $this->t('File name'),
  '#description' => $this->t(
    'Is suffixed by the exif creation date-time plus fid cleaned for urls. If not set the original file name will be used.'

$form['file']['path'] = [
  '#type' => 'textfield',
  '#title' => $this->t('File path'),
  '#placeholder' => 'path/to/directory',
  '#description' => $this->t(
    'Path to the files sub-directory, default is "photos". Sub-dirs will be create if necessary.'

I've tried using something like this in both validateForm() and submitForm().

$images = $form_state->getValue('images');
$file = File::load( $images[0] );

Although this changes the values of the $file object, it doesn't change the real path. The jpg files are also still in /sites/default/files/photos/ with their original name plus a unique counter.

So to repeat my question: How can I set the upload_location and the fileName of a managedFile dynamically and programmatically in a submitForm() or validateForm() function using methods that are not marked deprecated in drupal 8.


1 Answer 1


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->getValue('images');
$file = File::load( $images[0] );


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

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

$file = File::load( $images[0] );
dpm($file->getFilename()); // returns test-02.jpg
dpm($file->getFileUri());  // returns public://photos/test/test-02.jpg
  • This works for me too, but I had to check if the directory exists $this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
    – Giuseppe
    Jun 13, 2022 at 10:28

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.