diff --git a/includes/form.inc b/includes/form.inc
index 38ef41c..66b0b6a 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -1322,25 +1322,30 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
     }
 
     // Make sure a value is passed when the field is required.
-    if (isset($elements['#needs_validation']) && $elements['#required']) {
-      // A simple call to empty() will not cut it here as some fields, like
-      // checkboxes, can return a valid value of '0'. Instead, check the
-      // length if it's a string, and the item count if it's an array.
-      // An unchecked checkbox has a #value of integer 0, different than string
-      // '0', which could be a valid value.
-      $is_empty_multiple = (!count($elements['#value']));
-      $is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
-      $is_empty_value = ($elements['#value'] === 0);
-      if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
-        // Although discouraged, a #title is not mandatory for form elements. In
-        // case there is no #title, we cannot set a form error message.
-        // Instead of setting no #title, form constructors are encouraged to set
-        // #title_display to 'invisible' to improve accessibility.
-        if (isset($elements['#title'])) {
-          form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
-        }
-        else {
-          form_error($elements);
+    if (isset($elements['#needs_validation']) && $elements['#required']) { 
+
+      // Specialized check for file type uploads, which store their
+      // value in the $_FILES array.
+      if ($elements['#type'] !== 'file' || empty($_FILES['files']['name'][$elements['#parents'][0]])) {
+        // A simple call to empty() will not cut it here as some fields, like
+        // checkboxes, can return a valid value of '0'. Instead, check the
+        // length if it's a string, and the item count if it's an array.
+        // An unchecked checkbox has a #value of integer 0, different than string
+        // '0', which could be a valid value.
+        $is_empty_multiple = (!count($elements['#value']));
+        $is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
+        $is_empty_value = ($elements['#value'] === 0);
+        if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
+          // Although discouraged, a #title is not mandatory for form elements. In
+          // case there is no #title, we cannot set a form error message.
+          // Instead of setting no #title, form constructors are encouraged to set
+          // #title_display to 'invisible' to improve accessibility.
+          if (isset($elements['#title'])) {
+            form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+          }
+          else {
+            form_error($elements);
+          }
         }
       }
     }
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index dc12b1b..79bbe1a 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -654,6 +654,26 @@ class FileSaveUploadTest extends FileHookTestCase {
   }
 
   /**
+   * Test the file_save_upload() function with required file field.
+   */
+  function testRequired() {
+    // Reset the hook counters to get rid of the 'load' we just called.
+    file_test_reset();
+
+    // Upload a second file.
+    $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {file}')->fetchField();
+    $image2 = current($this->drupalGetTestFiles('image'));
+    $edit = array('files[file_test_upload]' => drupal_realpath($image2->uri));
+    $this->drupalPost('file-test/upload/1', $edit, t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('You WIN!'));
+    
+    $this->drupalPost('file-test/upload/1', array(), t('Submit'));
+    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
+    $this->assertRaw(t('field is required'));
+  }
+
+  /**
    * Test extension handling.
    */
   function testHandleExtension() {
diff --git a/modules/simpletest/tests/file_test.module b/modules/simpletest/tests/file_test.module
index 2865a1f..41d65db 100644
--- a/modules/simpletest/tests/file_test.module
+++ b/modules/simpletest/tests/file_test.module
@@ -43,10 +43,11 @@ function file_test_stream_wrappers() {
 /**
  * Form to test file uploads.
  */
-function _file_test_form($form, &$form_state) {
+function _file_test_form($form, &$form_state, $required = FALSE) {
   $form['file_test_upload'] = array(
     '#type' => 'file',
     '#title' => t('Upload a file'),
+    '#required' => $required,
   );
   $form['file_test_replace'] = array(
     '#type' => 'select',
