Unable to retrieve uploaded file in submit handler I'm creating a custom form with a file upload field that will have its contents read, processed then sent to an external API. The problem is whenever I upload the file the field for it appears to be empty in the submit handler and I cannot see why.

In this example I'm using it as an unmanaged file as I only need to process it then remove it but I have tried it as a managed file which does upload (I can see it in the directory) and has the file added to the file_managed database table. I'm not sure where unmanaged file are meant to go to check for their upload.

public function buildForm(array $form, FormStateInterface $form_state) {
    $form = [
      '#attributes' =&gt; ['enctype' =&gt; 'multipart/form-data'],
    ];

    $form['file_upload_details'] = [
      '#markup' =&gt; "&lt;strong&gt;" . $this-&gt;t('The KML File') . "&lt;/strong&gt;",
    ];

    $form['my_file'] = [
      '#type' =&gt; 'file',
      '#description' =&gt; $this-&gt;t('KML format only'),
      '#upload_location' =&gt; 'public://my_files/',
      '#upload_validators' =&gt; [
        'file_validate_extensions' =&gt; ['kml'],
      ],
    ];

    $form_build = parent::buildForm($form, $form_state);

    return $form_build;
  }


  public function submitForm(array &amp;$form, FormStateInterface $form_state) {
    $messenger = parent::messenger();

var_dump(
  $form_state-&gt;getStorage(), // Empty array
  $form_state-&gt;getValue('my_file') // Empty string
);
  }
All what '#type' =&gt; 'file' form elements do is to provide a bare &lt;input type="file"&gt; element. You get a prompt to select a file from your machine and on form submit the browser sends a request to your server, server forwards it to PHP, PHP extracts the file from the request, PHP stores it to the server's temp dir and when the script ends it deletes it again. Not much Drupal involved.

If you need to handle the file somehow and be it just the filename you need to take care of it yourself. And that's what file_save_upload() is for. It expects the $form_field_name as first parameter. And it will return you the file information. When scanning core for '#type' =&gt; 'file' you will often see this function being used in the form validation handler. Where the return value is being passed back to $form_state. For example in \Drupal\system\Form\ThemeSettingsForm::validateForm(). Just this time the function is wrapped from _file_save_upload_from_form() to allow correct error handling in forms.


// Check for a new uploaded logo.
if (isset($form['logo'])) {
  $file = _file_save_upload_from_form($form['logo']['settings']['logo_upload'], $form_state, 0);
  if ($file) {
    // Put the temporary file in form_values so we can save it on submit.
    $form_state-&gt;setValue('logo_upload', $file);
  }
}