diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc
index 5508b9b..9016e8b 100644
--- a/modules/file/file.field.inc
+++ b/modules/file/file.field.inc
@@ -447,32 +447,18 @@ function file_field_widget_form(&$form, &$form_state, $field, $instance, $langco
     'description' => '',
   );
 
-  // Retrieve any values set in $form_state, as will be the case during Ajax
-  // rebuilds of this form.
-  if (isset($form_state['values'])) {
-    $path = array_merge($element['#field_parents'], array($field['field_name'], $langcode));
-    $path_exists = FALSE;
-    $values = drupal_array_get_nested_value($form_state['values'], $path, $path_exists);
-    if ($path_exists) {
-      $items = $values;
-      drupal_array_set_nested_value($form_state['values'], $path, NULL);
-    }
-  }
+  // Determine the number of widgets to display.
+  switch ($field['cardinality']) {
+    case FIELD_CARDINALITY_UNLIMITED:
+      $field_state = field_form_get_state($element['#field_parents'], $field['field_name'], $langcode, $form_state);
+      $max = $field_state['items_count'];
+      break;
 
-  foreach ($items as $delta => $item) {
-    $items[$delta] = array_merge($defaults, $items[$delta]);
-    // Remove any items from being displayed that are not needed.
-    if ($items[$delta]['fid'] == 0) {
-      unset($items[$delta]);
-    }
+    default:
+      $max = $field['cardinality'] - 1;
+      break;
   }
 
-  // Re-index deltas after removing empty items.
-  $items = array_values($items);
-
-  // Update order according to weight.
-  $items = _field_sort_items($field, $items);
-
   // Essentially we use the managed_file type, extended with some enhancements.
   $element_info = element_info('managed_file');
   $element += array(
@@ -495,18 +481,18 @@ function file_field_widget_form(&$form, &$form_state, $field, $instance, $langco
   }
   else {
     // If there are multiple values, add an element for each existing one.
-    $delta = -1;
-    foreach ($items as $delta => $item) {
+    for ($delta = 0; $delta < $max; $delta++) {
       $elements[$delta] = $element;
-      $elements[$delta]['#default_value'] = $item;
+      $elements[$delta]['#default_value'] = isset($items[$delta]) ? $items[$delta] : $defaults;
       $elements[$delta]['#weight'] = $delta;
+      $elements[$delta]['#delta'] = $delta;
     }
     // And then add one more empty row for new uploads.
-    $delta++;
-    if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $field['cardinality']) {
+    if (($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $field['cardinality']) && empty($form_state['programmed'])) {
       $elements[$delta] = $element;
       $elements[$delta]['#default_value'] = $defaults;
       $elements[$delta]['#weight'] = $delta;
+      $elements[$delta]['#delta'] = $delta;
       $elements[$delta]['#required'] = ($element['#required'] && $delta == 0);
     }
     // The group of elements all-together need some extra functionality
@@ -754,6 +740,38 @@ function file_field_widget_submit($form, &$form_state) {
   // so nothing is lost in doing this.
   $parents = array_slice($form_state['triggering_element']['#parents'], 0, -2);
   drupal_array_set_nested_value($form_state['input'], $parents, NULL);
+
+
+  $button = $form_state['triggering_element'];
+
+  // Go one level up in the form, to the widgets container.
+  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
+  $field_name = $element['#field_name'];
+  $langcode = $element['#language'];
+  $parents = $element['#field_parents'];
+
+  $submitted_values = drupal_array_get_nested_value($form_state['values'], array_slice($button['#array_parents'], 0, -2));
+  $count = 0;
+  foreach ($submitted_values as $delta => $submitted_value) {
+    if ($submitted_value['fid']) {
+      $count++;
+    }
+    else {
+      unset($submitted_values[$delta]);
+    }
+  }
+
+  // Re-index deltas after removing empty items.
+  $submitted_values = array_values($submitted_values);
+
+  // Update form_state values and input.
+  form_set_value($element, $submitted_values, $form_state);
+  drupal_array_set_nested_value($form_state['values'], array_slice($button['#array_parents'], 0, -2), $submitted_values);
+
+  // Update items count.
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+  $field_state['items_count'] = $count;
+  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
 }
 
 /**
diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test
index 99f95b4..d7a5378 100644
--- a/modules/file/tests/file.test
+++ b/modules/file/tests/file.test
@@ -370,7 +370,7 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
   }
 
   /**
-   * Tests upload and remove buttons, with and without Ajax, for a multi-valued File field.
+   * Tests upload and remove buttons, with and without Ajax, for multiple multi-valued File field.
    */
   function testMultiValuedWidget() {
     // Use 'page' instead of 'article', so that the 'article' image field does
@@ -379,10 +379,16 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
     // using a custom node type.
     $type_name = 'page';
     $field_name = strtolower($this->randomName());
+    $field_name2 = strtolower($this->randomName());
     $this->createFileField($field_name, $type_name, array('cardinality' => 3));
+    $this->createFileField($field_name2, $type_name, array('cardinality' => 3));
+
     $field = field_info_field($field_name);
     $instance = field_info_instance('node', $field_name, $type_name);
 
+    $field2 = field_info_field($field_name2);
+    $instance2 = field_info_instance('node', $field_name2, $type_name);
+
     $test_file = $this->getTestFile('text');
 
     foreach (array('nojs', 'js') as $type) {
@@ -392,13 +398,15 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
       // @todo This is only testing a non-Ajax upload, because drupalPostAJAX()
       //   does not yet emulate jQuery's file upload.
       $this->drupalGet("node/add/$type_name");
-      for ($delta = 0; $delta < 3; $delta++) {
-        $edit = array('files[' . $field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']' => drupal_realpath($test_file->uri));
-        // If the Upload button doesn't exist, drupalPost() will automatically
-        // fail with an assertion message.
-        $this->drupalPost(NULL, $edit, t('Upload'));
+      foreach (array($field_name, $field_name2) as $each_field_name) {
+        for ($delta = 0; $delta < 3; $delta++) {
+          $edit = array('files[' . $each_field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']' => drupal_realpath($test_file->uri));
+          // If the Upload button doesn't exist, drupalPost() will automatically
+          // fail with an assertion message.
+          $this->drupalPost(NULL, $edit, t('Upload'));
+        }
       }
-      $this->assertNoFieldByXpath('//input[@type="submit"]', t('Upload'), t('After uploading 3 files, the "Upload" button is no longer displayed.'));
+      $this->assertNoFieldByXpath('//input[@type="submit"]', t('Upload'), t('After uploading 3 files for each field, the "Upload" button is no longer displayed.'));
 
       // Test clicking each "Remove" button. For extra robustness, test them out
       // of sequential order. They are 0-indexed, and get renumbered after each
@@ -406,14 +414,14 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
       // - First remove the 2nd file.
       // - Then remove what is then the 2nd file (was originally the 3rd file).
       // - Then remove the first file.
-      $num_expected_remove_buttons = 3;
+      $num_expected_remove_buttons = 6;
       foreach (array(1, 1, 0) as $delta) {
         // Ensure we have the expected number of Remove buttons, and that they
         // are numbered sequentially.
         $buttons = $this->xpath('//input[@type="submit" and @value="Remove"]');
         $this->assertTrue(is_array($buttons) && count($buttons) === $num_expected_remove_buttons, t('There are %n "Remove" buttons displayed (JSMode=%type).', array('%n' => $num_expected_remove_buttons, '%type' => $type)));
         foreach ($buttons as $i => $button) {
-          $this->assertIdentical((string) $button['name'], $field_name . '_' . LANGUAGE_NONE . '_' . $i . '_remove_button');
+          $this->assertIdentical((string) $button['name'], ($i > 2 ? $field_name2 : $field_name) . '_' . LANGUAGE_NONE . '_' . $i % 3 . '_remove_button');
         }
 
         // "Click" the remove button (emulating either a nojs or js submission).
@@ -443,9 +451,9 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
         $num_expected_remove_buttons--;
 
         // Ensure we have a single Upload button, and that it is numbered
-        // sequentially after the Remove buttons.
+        // according to the deleted element.
         $buttons = $this->xpath('//input[@type="submit" and @value="Upload"]');
-        $this->assertTrue(is_array($buttons) && count($buttons) == 1 && ((string) $buttons[0]['name'] === ($field_name . '_' . LANGUAGE_NONE . '_' . $num_expected_remove_buttons . '_upload_button')), t('After removing a file, an "Upload" button is displayed (JSMode=%type).'));
+        $this->assertTrue(is_array($buttons) && count($buttons) == 1 && ((string) $buttons[0]['name'] === ($field_name . '_' . LANGUAGE_NONE . '_' . ($num_expected_remove_buttons - 3) . '_upload_button')), t('After removing a file, an "Upload" button is displayed (JSMode=%type).', array('%type' => $type)));
       }
 
       // Ensure the page now has no Remove buttons.
diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php
index a0cd114..19e11d0 100644
--- a/modules/simpletest/drupal_web_test_case.php
+++ b/modules/simpletest/drupal_web_test_case.php
@@ -2237,7 +2237,7 @@ class DrupalWebTestCase extends DrupalTestCase {
             break;
           case 'submit':
           case 'image':
-            if (isset($submit) && $submit == $value) {
+            if (isset($submit) && $submit == $value && !$submit_matches) {
               $post[$name] = $value;
               $submit_matches = TRUE;
             }
