diff --git a/modules/ds_search/ds_search.install b/modules/ds_search/ds_search.install
index bc3963d..2ed2077 100644
--- a/modules/ds_search/ds_search.install
+++ b/modules/ds_search/ds_search.install
@@ -12,6 +12,7 @@ function ds_search_uninstall() {
   variable_del('ds_search_type');
   variable_del('ds_search_path');
   variable_del('ds_search_view_mode');
+  variable_del('ds_search_file_render');
   variable_del('ds_search_variables');
   variable_del('ds_search_show_title');
   variable_del('ds_search_language');
diff --git a/modules/ds_search/ds_search.module b/modules/ds_search/ds_search.module
index 2b63aac..0738947 100644
--- a/modules/ds_search/ds_search.module
+++ b/modules/ds_search/ds_search.module
@@ -211,12 +211,14 @@ function ds_search_invoke_node_search($hook) {
 }
 
 /**
- * DS entity view callback. Straight copy from Entity API module with fallback
- * to Drupal core view callbacks for nodes .
+ * DS entity view callback.
+ *
+ * Straight copy from Entity API module with fallback to Drupal core
+ * view callbacks for nodes, files and maybe others later.
  */
 function ds_entity_view_fallback($entity_type, $entities, $view_mode = 'full', $langcode = NULL, $page = NULL) {
 
-  // Entity support for entity search.
+  // Use the entity module in case it's enabled.
   if (module_exists('entity')) {
     return entity_view($entity_type, $entities, $view_mode, $langcode, $page);
   }
@@ -224,7 +226,7 @@ function ds_entity_view_fallback($entity_type, $entities, $view_mode = 'full', $
     if ($entity_type == 'node') {
       return node_view_multiple($entities, $view_mode);
     }
-    elseif ($entity_type == 'file') {
+    elseif ($entity_type == 'file' && function_exists('file_view_multiple')) {
       return file_view_multiple($entities, $view_mode);
     }
   }
@@ -246,164 +248,193 @@ function ds_search_search_page($results) {
   }
   else {
     foreach ($results as $id => $result) {
+      // Use default search result theming for file in case it's configured.
+      if ($result->entity_type == 'file' && variable_get('ds_search_file_render', FALSE)) {
+        $build['search_results'][] = array(
+          '#weight' => $i++,
+          '#markup' => theme('search_result', array('result' => $result->original_result, 'module' => 'apachesolr_search')),
+        );
+        continue;
+      }
       $entity_type = isset($result->entity_type) ? $result->entity_type : 'node';
       $data = ds_entity_view_fallback($entity_type, array($result->entity_id => $result), variable_get('ds_search_view_mode', 'search_result'));
-      $data = reset($data);
-      $data[$result->entity_id]['#weight'] = $i++;
-      $build['search_results'][] = $data[$result->entity_id];
-      unset($results[$result->entity_id]);
-      unset($result);
+      // Check that we got an actual result back.
+      if ($data) {
+        $data = reset($data);
+        $data[$result->entity_id]['#weight'] = $i++;
+        $build['search_results'][] = $data[$result->entity_id];
+      }
     }
   }
 
   // Group by type.
   if (variable_get('ds_search_group_by_type') && variable_get('ds_search_group_by_type_settings') && !empty($build['search_results'])) {
-
-    $settings = variable_get('ds_search_group_by_type_settings');
-    foreach ($build['search_results'] as $id => $result) {
-      if ($settings[$result['#bundle']]['status']) {
-
-        // Type group.
-        if (!isset($build['search_results'][$result['#bundle']])) {
-          $type = $settings[$result['#bundle']]['wrapper'];
-          $title = check_plain(t($settings[$result['#bundle']]['label']));
-          $class = 'group-result group-result-' . strtr($result['#bundle'], '_', '-');
-          $parity[$result['#bundle']] = 'odd';
-          $build['search_results'][$result['#bundle']] = array(
-            '#type' => $type,
-            '#title' => $title,
-            '#weight' => $settings[$result['#bundle']]['weight'],
-            '#attributes' => array(
-              'class' => array($class),
-            ),
-          );
-
-          if ($type == 'markup') {
-            $build['search_results'][$result['#bundle']]['#prefix'] = '<div class="' . $class . '">' . ((!empty($title)) ? ' <h2>' . $title . '</h2>' : '');
-            $build['search_results'][$result['#bundle']]['#suffix'] = '</div>';
-          }
-        }
-
-        // Move result into the wrapper of its type and unset previous.
-        $build['search_results'][$result['#bundle']][$id] = $result;
-        unset($build['search_results'][$id]);
-
-        // Add the parity to the result to enable correct zebra striping.
-        $build['search_results'][$result['#bundle']][$id]['#node']->ds_search_zebra = $parity[$result['#bundle']];
-        $parity[$result['#bundle']] = $parity[$result['#bundle']] == 'odd' ? 'even' : 'odd';
-      }
-      else {
-
-        // Other group.
-        if (!isset($build['search_results']['ds-other'])) {
-          $title = check_plain(t(variable_get('ds_search_group_by_type_other', 'Other')));
-          $type = variable_get('ds_search_group_by_type_other_wrapper', 'fieldset');
-          $class = 'group-result group-result-other';
-          $parity['ds-other'] = 'odd';
-          $build['search_results']['ds-other'] = array(
-            '#type' => $type,
-            '#title' => $title,
-            '#weight' => 100,
-            '#attributes' => array(
-              'class' => array($class),
-            ),
-          );
-
-          if ($type == 'markup') {
-            $build['search_results']['ds-other']['#prefix'] = '<div class="' . $class . '">' . ((!empty($title)) ? '<h2>' . $title . '</h2>' : '');
-            $build['search_results']['ds-other']['#suffix'] = '</div>';
-          }
-        }
-
-        // Move result into other wrapper and unset previous.
-        $build['search_results']['ds-other'][$id] = $result;
-        unset($build['search_results'][$id]);
-
-        // Add the parity to the result to enable correct zebra striping.
-        $build['search_results']['ds-other'][$id]['#node']->ds_search_parity = $parity['ds-other'];
-        $parity['ds-other'] = $parity['ds-other'] == 'odd' ? 'even' : 'odd';
-      }
-    }
+    _ds_search_group_by_type($build);
   }
   else {
     // Provide zebra striping for results that are not grouped.
     $parity = 'odd';
     foreach ($build['search_results'] as $id => $result) {
-      switch ($build['search_results'][$id]['#entity_type']) {
-        case 'taxonomy_term':
-          $key = '#term';
-          break;
-
-         default:
-           $key = '#' . $build['search_results'][$id]['#entity_type'];
-           break;
+      // We need to check on the entity type, as the container
+      // where the object is stored in doesn't necessarily reflect
+      // the name of the entity type.
+      if (!empty($build['search_results'][$id]['#entity_type'])) {
+        switch ($build['search_results'][$id]['#entity_type']) {
+          case 'taxonomy_term':
+            $key = '#term';
+            break;
+
+           default:
+             $key = '#' . $build['search_results'][$id]['#entity_type'];
+             break;
+        }
+
+        $build['search_results'][$id][$key]->ds_search_zebra = $parity;
       }
 
-      $build['search_results'][$id][$key]->ds_search_zebra = $parity;
+      // Let parity change always.
       $parity = $parity == 'odd' ? 'even' : 'odd';
     }
   }
 
   // Apache Solr multisearch grouping.
   if (variable_get('ds_search_apachesolr_multisite') && variable_get('ds_search_apachesolr_multisite_group') && variable_get('ds_search_type', 'node') == 'apachesolr_search') {
-    $site_counter = array();
-    $conf_array = array();
-    $config = explode("\n", variable_get('ds_search_apachesolr_multisite_group_config'));
-    foreach ($config as $weight => $conf) {
-      $conf = trim($conf);
-      if (empty($conf)) {
-        continue;
-      }
-      $site_conf = explode('|', $conf);
-      $conf_array[$site_conf[0]] = array(
-        'label' => $site_conf[1],
-        'wrapper' => $site_conf[2],
-        'weight' => $weight,
-      );
-    }
+    _ds_search_group_by_type_multisearch($build);
+  }
 
-    // Iterate over results.
-    foreach ($build['search_results'] as $id => $result) {
-      if (!isset($build['search_results'][$result['#site_hash']])) {
-        $class = 'group-result group-result-' . strtr($result['#site_hash'], '_', '-');
-        $build['search_results'][$result['#site_hash']] = array(
-          '#type' => 'fieldset',
-          '#weight' => $conf_array[$result['#site_hash']]['weight'],
+  return theme('ds_search_page', $build);
+}
+
+/**
+ * Helper function to group by type.
+ */
+function _ds_search_group_by_type(&$build) {
+  $settings = variable_get('ds_search_group_by_type_settings');
+  foreach ($build['search_results'] as $id => $result) {
+    if ($settings[$result['#bundle']]['status']) {
+
+      // Type group.
+      if (!isset($build['search_results'][$result['#bundle']])) {
+        $type = $settings[$result['#bundle']]['wrapper'];
+        $title = check_plain(t($settings[$result['#bundle']]['label']));
+        $class = 'group-result group-result-' . strtr($result['#bundle'], '_', '-');
+        $parity[$result['#bundle']] = 'odd';
+        $build['search_results'][$result['#bundle']] = array(
+          '#type' => $type,
+          '#title' => $title,
+          '#weight' => $settings[$result['#bundle']]['weight'],
           '#attributes' => array(
             'class' => array($class),
           ),
         );
 
-        // Create site counter.
-        $site_counter[$result['#site_hash']] = array(
-          'counter' => 0,
-          'title' => $conf_array[$result['#site_hash']]['label'],
-          'type' => $conf_array[$result['#site_hash']]['wrapper'],
-          'class' => $class,
-        );
+        if ($type == 'markup') {
+          $build['search_results'][$result['#bundle']]['#prefix'] = '<div class="' . $class . '">' . ((!empty($title)) ? ' <h2>' . $title . '</h2>' : '');
+          $build['search_results'][$result['#bundle']]['#suffix'] = '</div>';
+        }
       }
 
-      // Move result into other wrapper and unset previous. Also count for
-      // every site so we can populate @total_per_site later on.
-      $site_counter[$result['#site_hash']]['counter']++;
-      $build['search_results'][$result['#site_hash']][$id] = $result;
+      // Move result into the wrapper of its type and unset previous.
+      $build['search_results'][$result['#bundle']][$id] = $result;
       unset($build['search_results'][$id]);
+
+      // Add the parity to the result to enable correct zebra striping.
+      $build['search_results'][$result['#bundle']][$id]['#node']->ds_search_zebra = $parity[$result['#bundle']];
+      $parity[$result['#bundle']] = $parity[$result['#bundle']] == 'odd' ? 'even' : 'odd';
     }
+    else {
+
+      // Other group.
+      if (!isset($build['search_results']['ds-other'])) {
+        $title = check_plain(t(variable_get('ds_search_group_by_type_other', 'Other')));
+        $type = variable_get('ds_search_group_by_type_other_wrapper', 'fieldset');
+        $class = 'group-result group-result-other';
+        $parity['ds-other'] = 'odd';
+        $build['search_results']['ds-other'] = array(
+          '#type' => $type,
+          '#title' => $title,
+          '#weight' => 100,
+          '#attributes' => array(
+            'class' => array($class),
+          ),
+        );
 
-    // Site counter.
-    foreach ($site_counter as $hash => $values) {
-      $title = check_plain(t($values['title'], array('!total_per_site' => format_plural($values['counter'], '1 result', '@count results'))));
-      if ($values['type'] == 'div') {
-        $build['search_results'][$hash]['#prefix'] = '<div class="' . $values['class'] . '">' . ((!empty($title)) ? '<h2>' . $title . '</h2>' : '');
-        $build['search_results'][$hash]['#suffix'] = '</div>';
-      }
-      else {
-        $build['search_results'][$hash]['#title'] = $title;
+        if ($type == 'markup') {
+          $build['search_results']['ds-other']['#prefix'] = '<div class="' . $class . '">' . ((!empty($title)) ? '<h2>' . $title . '</h2>' : '');
+          $build['search_results']['ds-other']['#suffix'] = '</div>';
+        }
       }
+
+      // Move result into other wrapper and unset previous.
+      $build['search_results']['ds-other'][$id] = $result;
+      unset($build['search_results'][$id]);
+
+      // Add the parity to the result to enable correct zebra striping.
+      $build['search_results']['ds-other'][$id]['#node']->ds_search_parity = $parity['ds-other'];
+      $parity['ds-other'] = $parity['ds-other'] == 'odd' ? 'even' : 'odd';
     }
   }
+}
 
-  return theme('ds_search_page', $build);
+/**
+ * Helper function to perform grouping on Apache Solr multisearch.
+ */
+function _ds_search_group_by_type_multisearch(&$build) {
+  $site_counter = array();
+  $conf_array = array();
+  $config = explode("\n", variable_get('ds_search_apachesolr_multisite_group_config'));
+  foreach ($config as $weight => $conf) {
+    $conf = trim($conf);
+    if (empty($conf)) {
+      continue;
+    }
+    $site_conf = explode('|', $conf);
+    $conf_array[$site_conf[0]] = array(
+      'label' => $site_conf[1],
+      'wrapper' => $site_conf[2],
+      'weight' => $weight,
+    );
+  }
+
+  // Iterate over results.
+  foreach ($build['search_results'] as $id => $result) {
+    if (!isset($build['search_results'][$result['#site_hash']])) {
+      $class = 'group-result group-result-' . strtr($result['#site_hash'], '_', '-');
+      $build['search_results'][$result['#site_hash']] = array(
+        '#type' => 'fieldset',
+        '#weight' => $conf_array[$result['#site_hash']]['weight'],
+        '#attributes' => array(
+          'class' => array($class),
+        ),
+      );
+
+      // Create site counter.
+      $site_counter[$result['#site_hash']] = array(
+        'counter' => 0,
+        'title' => $conf_array[$result['#site_hash']]['label'],
+        'type' => $conf_array[$result['#site_hash']]['wrapper'],
+        'class' => $class,
+      );
+    }
+
+    // Move result into other wrapper and unset previous. Also count for
+    // every site so we can populate @total_per_site later on.
+    $site_counter[$result['#site_hash']]['counter']++;
+    $build['search_results'][$result['#site_hash']][$id] = $result;
+    unset($build['search_results'][$id]);
+  }
+
+  // Site counter.
+  foreach ($site_counter as $hash => $values) {
+    $title = check_plain(t($values['title'], array('!total_per_site' => format_plural($values['counter'], '1 result', '@count results'))));
+    if ($values['type'] == 'div') {
+      $build['search_results'][$hash]['#prefix'] = '<div class="' . $values['class'] . '">' . ((!empty($title)) ? '<h2>' . $title . '</h2>' : '');
+      $build['search_results'][$hash]['#suffix'] = '</div>';
+    }
+    else {
+      $build['search_results'][$hash]['#title'] = $title;
+    }
+  }
 }
 
 /**
@@ -675,6 +706,14 @@ function ds_search_process_results($results) {
       $entity->entity_type = $result['fields']['entity_type'];
       $entity->entity_id = $result['fields']['entity_id'];
 
+      // Add the original result on the entity too in case this is a file
+      // entity. Attachments have brittle support as the file entity only
+      // exists in media 1.x or file entity 2.x. Because of that, we're
+      // most likely will render files through theme('search_result').
+      if ($result['fields']['entity_type'] == 'file') {
+        $entity->original_result = $result;
+      }
+
       // Apache Solr multisite support.
       if (variable_get('ds_search_apachesolr_multisite')) {
 
@@ -704,8 +743,7 @@ function ds_search_process_results($results) {
  */
 function ds_search_apachesolr_search_page_alter(&$build, $search_page) {
   if (!empty($build['search_results']['#results'])) {
-    $results = $build['search_results']['#results'];
-    $results = ds_search_process_results($results);
+    $results = ds_search_process_results($build['search_results']['#results']);
     $build['search_results'] = ds_search_search_page($results);
   }
 }
diff --git a/modules/ds_search/includes/ds_search.admin.inc b/modules/ds_search/includes/ds_search.admin.inc
index 7fcf156..628c398 100644
--- a/modules/ds_search/includes/ds_search.admin.inc
+++ b/modules/ds_search/includes/ds_search.admin.inc
@@ -51,6 +51,13 @@ function ds_search_settings($form, $form_state) {
     '#options' => $view_mode_options,
   );
 
+  $form['general']['ds_search_file_render'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use default search theming for files'),
+    '#description' => t('File/attachment results are best supported when the file entity module is enabled. Toggle the checkbox in case it is not available or you want to use default search theming.'),
+    '#default_value' => variable_get('ds_search_file_render', FALSE),
+  );
+
   $form['general']['ds_search_variables'] = array(
     '#type' => 'radios',
     '#options' => array(
