diff --git a/file_entity.pages.inc b/file_entity.pages.inc
index 8281afc..6a9f26e 100644
--- a/file_entity.pages.inc
+++ b/file_entity.pages.inc
@@ -33,9 +33,31 @@ function file_entity_view_page($file) {
 
 /**
  * Form callback for adding media via an upload form.
- * @todo: should use the AJAX uploader
+ * 
+ * This is a multi step form which has 1-3 pages:
+ * - Upload file
+ * - Choose filetype
+ *   If there is only one candidate (based on mimetype) we will skip this step.
+ * - Edit fields
+ *   Skip this step if there are no fields on this entity type.
  */
 function file_entity_add_upload($form, &$form_state, array $options = array()) {
+  $step = isset($form_state['step']) ? $form_state['step'] : 1;
+  $form['#step'] = $step;
+  switch ($step) {
+    case 1:
+      return file_entity_add_upload_step_upload($form, $form_state, $options);
+    case 2:
+      return file_entity_add_upload_step_filetype($form, $form_state, $options);
+    case 3:
+      return file_entity_add_upload_step_fields($form, $form_state, $options);
+  }
+}
+
+/**
+ * Generate form fields for the first step in the add file wizard.
+ */
+function file_entity_add_upload_step_upload($form, &$form_state, array $options = array()) {
   // Set up file upload validators.
   $validators = array();
 
@@ -73,12 +95,13 @@ function file_entity_add_upload($form, &$form_state, array $options = array()) {
     '#progress_indicator' => 'bar',
     '#required' => TRUE,
     '#pre_render' => array('file_managed_file_pre_render', 'file_entity_managed_file_pre_render'),
+    '#default_value' => isset($form_state['storage']['upload']) ? $form_state['storage']['upload'] : NULL,
   );
 
   $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array(
+  $form['actions']['next'] = array(
     '#type' => 'submit',
-    '#value' => t('Submit'),
+    '#value' => t('Next'),
   );
 
   form_load_include($form_state, 'inc', 'file_entity', 'file_entity.pages');
@@ -87,6 +110,64 @@ function file_entity_add_upload($form, &$form_state, array $options = array()) {
 }
 
 /**
+ * Generate form fields for the second step in the add file wizard.
+ */
+function file_entity_add_upload_step_filetype($form, &$form_state, array $options = array()) {
+  
+  // @todo: When we have custom file entity types there may be multiple
+  // candidate types based on the mimetype. This page is to choose which
+  // type we want to be created. Fill $candidates with the options.
+  // @see http://drupal.org/node/1292382
+  $file = file_load($form_state['storage']['upload']);
+  $candidates = array(file_get_type($file) => file_get_type($file));
+  
+  $form['type'] = array(
+    '#type' => 'radios',
+    '#title' => t('File type'),
+    '#options' => $candidates,
+    '#default_value' => isset($form_state['storage']['type']) ? $form_state['storage']['type'] : NULL, 
+    '#required' => TRUE,
+  );
+  
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['previous'] = array(
+    '#type' => 'submit',
+    '#value' => t('Previous'),
+  );
+  $form['actions']['next'] = array(
+    '#type' => 'submit',
+    '#value' => t('Next'),
+  );
+  
+  return $form;
+}
+
+/**
+ * Generate form fields for the thirth step in the add file wizard.
+ */
+function file_entity_add_upload_step_fields($form, &$form_state, array $options = array()) {
+  
+  // Load the file and overwrite the filetype set on the previous screen.
+  $file = file_load($form_state['storage']['upload']);
+  $file->type = $form_state['storage']['type'];
+  
+  // Add fields.
+  field_attach_form('file', $file, $form, $form_state);
+  
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['previous'] = array(
+    '#type' => 'submit',
+    '#value' => t('Previous'),
+  );
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+  
+  return $form;
+}
+
+/**
  * Pre-render callback for adding validation descriptions to managed file elements.
  */
 function file_entity_managed_file_pre_render($element) {
@@ -102,37 +183,48 @@ function file_entity_managed_file_pre_render($element) {
 }
 
 /**
- * Upload a file.
+ * Submit handler for the add file form.
  */
 function file_entity_add_upload_submit($form, &$form_state) {
-  $file = file_load($form_state['values']['upload']);
-
-  if ($file) {
+  $form_state['storage'] = isset($form_state['storage']) ? $form_state['storage'] : array();
+  $step = isset($form_state['step']) ? $form_state['step'] : 1;
+  $form_state['storage'] = array_merge($form_state['storage'], $form_state['values']);
+  
+  // This var is set to TRUE when we are ready to save the file.
+  $save = FALSE;
+  
+  switch ($form_state['triggering_element']['#id']) {
+    case 'edit-next':
+      $form_state['rebuild'] = TRUE;
+      $form_state['step'] = $form['#step'] + 1;
+      break;
+    case 'edit-previous':
+      $form_state['rebuild'] = TRUE;
+      $form_state['step'] = $form['#step'] - 1;
+      break;
+    case 'edit-submit':
+      $save = TRUE;
+      break;
+  }
+  
+  
+  if ($save) {
+    $file = file_load($form_state['storage']['upload']);
+    $file->type = $form_state['storage']['type'];
     // The media browser widget does not use the 'display' field.
     $file->display = TRUE;
-
+    
     // Change the file from temporary to permanent.
     $file->status = FILE_STATUS_PERMANENT;
+    
+    // Save the form fields.
+    // Keep in mind that the values for the Field API fields must be in
+    // $form_state['values'] and not in ['storage']. This is true as long as
+    // the fields are on the last page of the multi step form.
+    entity_form_submit_build_entity('file', $file, $form, $form_state);
+    
     file_save($file);
-
-    $form_state['file'] = $file;
-    drupal_set_message(t('The file @name was uploaded', array('@name' => $file->filename)));
-  }
-  else {
-    drupal_set_message(t('An error occurred and no file was uploaded.'), 'error');
-    return;
-  }
-
-  // Redirect to the file edit page after submission.
-  if (file_entity_access('edit')) {
-    $destination = array('destination' => 'admin/content/file');
-    if (isset($_GET['destination'])) {
-      $destination = drupal_get_destination();
-      unset($_GET['destination']);
-    }
-    $form_state['redirect'] = array('file/' . $file->fid . '/edit', array('query' => $destination));
-  }
-  else {
+    
     $form_state['redirect'] = 'admin/content/file';
   }
 }
