Add image upload to theme configuration I'm trying to add an image upload to the theme settings in a theme I made. The image upload field does appear, however nothing actually gets uploaded and the image never get's saved.

in theme-settings.php I have the function

function mytheme_form_system_theme_settings_alter(&amp;$form, $form_state, $form_id = NULL) {
    $form['banner']['banner_image'] = array(
        '#type' =&gt; 'file',
        '#title' =&gt; t('Banner Image'),
        '#description' =&gt; t('Upload a banner image'),
        '#default_value' =&gt; theme_get_setting('banner_image'),
    );
}


The image upload field does appear, but when choosing the file and clicking 'save configuration' nothing actually gets saved.
The problem with your code is that it needs a submission handler to handle the uploaded file. Using #file as form element type is fine, since that is also done from Drupal core in system_theme_settings().

$form['logo']['settings']['logo_path'] = array(
  '#type' =&gt; 'textfield',
  '#title' =&gt; t('Path to custom logo'),
  '#description' =&gt; t('The path to the file you would like to use as your logo file instead of the default logo.'),
  '#default_value' =&gt; theme_get_setting('logo_path', $key),
);
$form['logo']['settings']['logo_upload'] = array(
  '#type' =&gt; 'file',
  '#title' =&gt; t('Upload logo image'),
  '#maxlength' =&gt; 40,
  '#description' =&gt; t("If you don't have direct file access to the server, use this field to upload your logo.")
);


The form submission handler (system_theme_settings_submit()) then handles the uploaded file with the following code.

  // Exclude unnecessary elements before saving.
  form_state_values_clean($form_state);

  $values = $form_state['values'];

  // Extract the name of the theme from the submitted form values, then remove
  // it from the array so that it is not saved as part of the variable.
  $key = $values['var'];
  unset($values['var']);

  // If the user uploaded a new logo or favicon, save it to a permanent location
  // and use it in place of the default theme-provided file.
  if (!empty($values['logo_upload'])) {
    $file = $values['logo_upload'];
    unset($values['logo_upload']);
    $filename = file_unmanaged_copy($file-&gt;uri);
    $values['default_logo'] = 0;
    $values['logo_path'] = $filename;
    $values['toggle_logo'] = 1;
  }


You could use similar code in a form submission handler, but as described in When theme-settings.php has a managed_file field and a submit callback, " Call to undefined function" error is thrown. such form aubmission handler would not be found because Drupal doesn't load the theme-settings.php file automatically.
If you get around that, and you are able to make Drupal automatically load the file containing the submission handler, you could use the following code in your submission handler.

  if (!empty($form_state['values']['banner_image'])) {
    $file = $form_state['values']['banner_image'];
    unset($form_state['values']['banner_image']);
    $filename = file_unmanaged_copy($file-&gt;uri);
    $form_state['values']['banner_image_path'] = $filename;
  }


With theme_get_setting('banner_image_path') you will then get the path of the last uploaded file.
I would do as Drupal does, and add a textfield for the path of the last uploaded file.