diff --git a/components/file.inc b/components/file.inc
index e1be9c1..9aa693a 100644
--- a/components/file.inc
+++ b/components/file.inc
@@ -346,13 +346,23 @@ function _webform_render_file($component, $value = NULL, $filter = TRUE, $submis
     $max_filesize = parse_size($set_filesize);
   }
 
+  if (isset($value[0])) {
+    $default_value = $value[0];
+  }
+  elseif (isset($value['fid'])) {
+    $default_value = $value['fid'];
+  }
+  else {
+    $default_value = NULL;
+  }
+
   $element = array(
     '#type' => 'managed_file',
     '#theme' => 'webform_managed_file',
     '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'],
     '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
     '#required' => $component['required'],
-    '#default_value' => isset($value[0]) ? $value[0] : NULL,
+    '#default_value' => $default_value,
     '#attributes' => $component['extra']['attributes'],
     '#upload_validators' => array(
       'file_validate_size' => array($max_filesize),
diff --git a/webform.info b/webform.info
index f58d24f..0529079 100644
--- a/webform.info
+++ b/webform.info
@@ -39,4 +39,5 @@ files[] = tests/components.test
 files[] = tests/conditionals.test
 files[] = tests/permissions.test
 files[] = tests/submission.test
+files[] = tests/submission.file.test
 files[] = tests/webform.test
diff --git a/webform.module b/webform.module
index 56f4b17..977a552 100644
--- a/webform.module
+++ b/webform.module
@@ -2584,7 +2584,31 @@ function webform_client_form($form, &$form_state, $node, $submission = FALSE, $r
         $prev_page_labels[$component['page_num']] = !empty($component['extra']['prev_page_label']) ? t($component['extra']['prev_page_label']) : t('< Previous Page');
       }
       if (!$filter || $sorter->componentVisibility($cid, $page_num)) {
-        $component_value = isset($input_values[$cid]) ? $input_values[$cid] : NULL;
+        if (isset($input_values[$cid])) {
+          $component_value = $input_values[$cid];
+        }
+        elseif (isset($input_values[$component['form_key']])) {
+          $component_value = $input_values[$component['form_key']];
+          // Hack to support multiple files on the same form. Do this for file
+          // components as well as any component that has children (since the
+          // children might contain file components of their own).
+          if ($component['type'] == 'file' || !empty($component['children'])) {
+            if (!isset($form_state['webform_file_storage'])) {
+              $form_state['webform_file_storage'] = array();
+            }
+            // Merge the current submitted file into $form_state storage so it
+            // can be used to populate the file widget on subsequent Ajax
+            // requests.
+            $form_state['webform_file_storage'] = drupal_array_merge_deep($form_state['webform_file_storage'], $input_values);
+          }
+        }
+        elseif (isset($form_state['webform_file_storage'][$component['form_key']])) {
+          // Use the file storage from above, if available.
+          $component_value = $form_state['webform_file_storage'][$component['form_key']];
+        }
+        else {
+          $component_value = NULL;
+        }
         _webform_client_form_add_component($node, $component, $component_value, $form['submitted'], $form, $input_values, 'form', $page_num, $filter);
       }
     }
@@ -2841,7 +2865,15 @@ function _webform_client_form_add_component($node, $component, $component_value,
   if (isset($component['children']) && is_array($component['children'])) {
     $sorter = webform_get_conditional_sorter($node);
     foreach ($component['children'] as $scid => $subcomponent) {
-      $subcomponent_value = isset($input_values[$scid]) ? $input_values[$scid] : NULL;
+      if (isset($input_values[$scid])) {
+        $subcomponent_value = $input_values[$scid];
+      }
+      elseif (isset($component_value[$subcomponent['form_key']])) {
+        $subcomponent_value = $component_value[$subcomponent['form_key']];
+      }
+      else {
+        $subcomponent_value = NULL;
+      }
       // Include if always shown, or for forms, also if currently hidden but might be shown due to conditionals.
       $visibility = $sorter->componentVisibility($scid, $subcomponent['page_num']);
       if ($visibility == WebformConditionals::componentShown || ($format == 'form' && $visibility) || !$filter) {
diff --git a/tests/submission.file.test b/tests/submission.file.test
new file mode 100644
index 0000000..383b258
--- /dev/null
+++ b/tests/submission.file.test
@@ -0,0 +1,462 @@
+<?php
+
+/**
+ * @file
+ * Webform module submission tests that focus on file components.
+ */
+
+class WebformFileSubmissionTestCase extends WebformTestHelper {
+  /**
+   * Implements getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Webform file submission'),
+      'description' => t('Submits a sample webform and checks the database integrity for file components.'),
+      'group' => t('Webform'),
+    );
+  }
+
+  /**
+   * Test that a form can have a file component added and have it show for
+   * authenticated visitors.
+   */
+  function testAuthBasicSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Run the basic submission tests against this webform.
+    $this->basicSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+  }
+
+  /**
+   * Test that a form can have a file component added and have it show for
+   * anonymous visitors.
+   */
+  function testAnonymousBasicSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Logout.
+    $this->drupalLogout();
+
+    // Run the basic submission tests against this webform.
+    $this->basicSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+  }
+
+  /**
+   * Confirm a file can be submitted by an authenticated user.
+   */
+  function testAuthFileSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Run the image file submission tests.
+    $this->fileSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Confirm a file can be submitted by an anonymous user.
+   */
+  function testAnonymousFileSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Logout.
+    $this->drupalLogout();
+
+    // Run the image file submission tests.
+    $this->fileSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Confirm that a file can be submitted when another component is required.
+   */
+  function testAuthFileRequiredSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Run the submission tests.
+    $this->fileRequiredSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Confirm that a file can be submitted by anonymous visitors when another
+   * component is required.
+   */
+  function testAnonymousFileRequiredSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Logout.
+    $this->drupalLogout();
+
+    // Run the submission tests.
+    $this->fileRequiredSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Confirm multiple files can be submitted by authenticated visitors.
+   */
+  function testAuthMultipleFileSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Run the submission tests.
+    $this->fileMultipleSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Confirm multiple files can be submitted by anonymous visitors.
+   */
+  function testAnonymousMultipleFileSubmission() {
+    // Create the node with a file component.
+    $node = $this->createTestWebform();
+
+    // Logout.
+    $this->drupalLogout();
+
+    // Run the submission tests.
+    $this->fileMultipleSubmissionTest($node->nid);
+
+    // Confirm the submission was successful.
+    $this->assertSubmission($node->nid);
+    $this->assertFileSubmission($node->nid);
+  }
+
+  /**
+   * Creates a webform with a text component and a file component.
+   *
+   * @return object
+   *   A node StdClass object.
+   */
+  function createTestWebform() {
+    $this->drupalLogin($this->webform_users['admin']);
+    $this->webformReset();
+
+    // Create the Webform test node, and only keep the plain text component.
+    $node = $this->getTestWebformNode();
+    $node = node_load($node->nid);
+
+    // Delete components that aren't text components, to keep the form simpler.
+    foreach ($node->webform['components'] as $key => $component) {
+      if ($component['form_key'] != 'textfield') {
+        unset($node->webform['components'][$key]);
+      }
+    }
+
+    // Add a file component.
+    $node->webform['components'][] = array(
+      'name' => 'File',
+      'form_key' => 'file_1',
+      'type' => 'file',
+      'value' => '',
+      'pid' => '0',
+      'required' => '0',
+      'weight' => '-12',
+      'extra' => array(
+        'title_display' => 'before',
+        'private' => 0,
+        'progress_indicator' => 'throbber',
+        'filtering' => array(
+          'size' => '5 MB',
+          'types' => array(
+            'gif',
+            'jpg',
+            'png',
+            'bmp',
+            'tif',
+            'pict',
+            'psd',
+            'txt',
+            'rtf',
+            'html',
+            'odf',
+            'pdf',
+            'doc',
+            'docx',
+            'ppt',
+            'pptx',
+            'xls',
+            'xlsx',
+            'xml',
+            'avi',
+            'mov',
+            'mp3',
+            'ogg',
+            'wav',
+            'zip',
+          ),
+          'addextensions' => '',
+        ),
+      ),
+    );
+    node_save($node);
+
+    // Reload the node.
+    $node = node_load($node->nid);
+
+    // Output a debug version of this node for later.
+    $this->verbose(print_r($node, TRUE));
+
+    return $node;
+  }
+
+  /**
+   * Run basic tests for a given Webform node.
+   *
+   * @param int $nid
+   *   The node ID to test against.
+   */
+  function basicSubmissionTest($nid) {
+    // Load the form and confirm the components exist.
+    $this->drupalGet('node/' . $nid);
+    $this->assertResponse(200);
+
+    // Confirm that the two components are present.
+    $this->assertFieldByName('submitted[textfield]', '', 'Found the text component.');
+    $this->assertFieldByName('files[submitted_file_1]', '', 'Found the file component.');
+    $this->assertFieldByName('submitted_file_1_upload_button', '', 'Found the file component upload button.');
+
+    // Submit the form, confirm that the submission went ok.
+    $this->drupalPost('node/' . $nid, array(), 'Submit', array(), array(), 'webform-client-form-' . $nid);
+    $this->assertResponse(200);
+    $this->assertText(t('Thanks!'));
+  }
+
+  /**
+   * Generate a test image.
+   *
+   * @return object
+   *   A file object.
+   */
+  function getTestImage() {
+    // Get a file to upload.
+    $file = current($this->drupalGetTestFiles('image'));
+
+    // Add a filesize property to files as would be read by file_load().
+    $file->filesize = filesize($file->uri);
+
+    return $file;
+  }
+
+  /**
+   * Generate a test text file.
+   *
+   * @return object
+   *   A file object.
+   */
+  function getTestText() {
+    // Get a file to upload.
+    $file = current($this->drupalGetTestFiles('text'));
+
+    // Add a filesize property to files as would be read by file_load().
+    $file->filesize = filesize($file->uri);
+
+    return $file;
+  }
+
+  /**
+   * Run file tests for a given Webform node.
+   *
+   * @param int $nid
+   *   The node ID to test against.
+   */
+  function fileSubmissionTest($nid) {
+    // Generate an example image.
+    $image = $this->getTestImage();
+
+    // Submit the webform with a file.
+    $edit = array();
+    $edit['files[submitted_file_1]'] = drupal_realpath($image->uri);
+    $this->drupalPost('node/' . $nid, $edit, 'Submit', array(), array(), 'webform-client-form-' . $nid);
+    $this->assertResponse(200);
+    $this->assertText(t('Thanks!'));
+  }
+
+  /**
+   * Run file tests for a given Webform node with required text field.
+   *
+   * @param int $nid
+   *   The node ID to test against.
+   */
+  function fileRequiredSubmissionTest($nid) {
+    $node = node_load($nid);
+
+    // Make the text field required.
+    foreach ($node->webform['components'] as &$component) {
+      if ($component['type'] == 'textfield') {
+        $component['required'] = '1';
+      }
+    }
+    node_save($node);
+
+    // Reload the node.
+    $node = node_load($nid);
+
+    // Generate an example image.
+    $image = $this->getTestImage();
+
+    // Submit the webform with a file but also a missing required text field, to
+    // confirm that the file can still be submitted.
+    $edit = array();
+    $edit['files[submitted_file_1]'] = drupal_realpath($image->uri);
+    $this->drupalPost('node/' . $nid, $edit, 'Submit', array(), array(), 'webform-client-form-' . $nid);
+    $this->assertResponse(200);
+    $this->assertNoText(t('Thanks!'));
+
+    foreach ($node->webform['components'] as $component) {
+      if ($component['type'] == 'textfield') {
+        $this->assertText(t('!name field is required.', array('!name' => $component['name'])));
+      }
+    }
+
+    // Submit the form again but this time with the missing field. This should
+    // still work.
+    $edit = array(
+      'submitted[textfield]' => 'Test submission',
+    );
+    $this->drupalPost(NULL, $edit, 'Submit', array(), array(), 'webform-client-form-' . $nid);
+    $this->assertResponse(200);
+    $this->assertText(t('Thanks!'));
+  }
+
+  /**
+   * Run multiple-file tests for a given Webform node.
+   *
+   * @param int $nid
+   *   The node ID to test against.
+   */
+  function fileMultipleSubmissionTest($nid) {
+    $node = node_load($nid);
+
+    // Make the text field required.
+    foreach ($node->webform['components'] as &$component) {
+      if ($component['type'] == 'file') {
+        $file_component = $component;
+      }
+    }
+    $file_component['form_key'] = 'file_2';
+    $file_component['weight']++;
+    unset($file_component['cid']);
+    $node->webform['components'][] = $file_component;
+    node_save($node);
+
+    // Reload the node.
+    $node = node_load($nid);
+
+    // Generate example images.
+    $image = $this->getTestImage();
+    $file = $this->getTestText();
+
+    // Submit the webform with a file.
+    $edit = array(
+      'files[submitted_file_1]' => drupal_realpath($image->uri),
+      'files[submitted_file_2]' => drupal_realpath($file->uri),
+    );
+    $this->drupalPost('node/' . $nid, $edit, 'Submit', array(), array(), 'webform-client-form-' . $nid);
+    $this->assertResponse(200);
+    $this->assertText(t('Thanks!'));
+  }
+
+  /**
+   * Confirm a submission was found.
+   *
+   * @param int $nid
+   *   The node ID to check against.
+   *
+   * @return bool
+   */
+  function assertSubmission($nid, $message = '', $group = 'Other') {
+    $found = db_query("SELECT sid
+      FROM {webform_submissions}
+      WHERE nid = :nid",
+      array(
+        ':nid' => $nid,
+      ))
+      ->fetchField();
+
+    return $this->assert((bool) $found, $message ? $message : t('Submission was found for Webform @value.', array('@value' => $nid)), $group);
+  }
+
+  /**
+   * Confirm a submitted file was found.
+   *
+   * @param int $nid
+   *   The node ID to check against.
+   *
+   * @return bool
+   */
+  function assertFileSubmission($nid, $message = '', $group = 'Other') {
+    $found = db_query("SELECT sid
+      FROM {webform_submissions}
+      WHERE nid = :nid",
+      array(
+        ':nid' => $nid,
+      ))
+      ->fetchField();
+    $found = intval($found);
+
+    // If nothing was found then there's no point in searching for a file.
+    if (!empty($found)) {
+      $sid = $found;
+
+      // Load the full node object.
+      $node = node_load($nid);
+
+      // Get the file component.
+      $cids = array();
+      foreach ($node->webform['components'] as $component) {
+        if ($component['type'] == 'file') {
+          $cids[] = $component['cid'];
+        }
+      }
+
+      // Look for the submitted file(s).
+      $found = array();
+      foreach ($cids as $cid) {
+        $found_it = db_query("SELECT data
+          FROM {webform_submitted_data}
+          WHERE nid = :nid
+          AND sid = :sid
+          AND cid = :cid",
+          array(
+            ':nid' => $nid,
+            ':sid' => $sid,
+            ':cid' => $cid,
+          ))->fetchField();
+        $found[] = intval($found_it);
+      }
+      $found = count($found) == count($cids);
+    }
+
+    return $this->assert((bool) $found, $message ? $message : t('File found in submission for Webform nid @value.', array('@value' => $nid)), $group);
+  }
+
+}
