diff --git a/config/install/search_api_attachments.admin_config.yml b/config/install/search_api_attachments.admin_config.yml
index 07ba765..58b7433 100644
--- a/config/install/search_api_attachments.admin_config.yml
+++ b/config/install/search_api_attachments.admin_config.yml
@@ -14,3 +14,6 @@ tika_extractor_configuration:
 python_pdf2txt_extractor_configuration:
   python_path: 'python'
   python_pdf2txt_script: '/usr/bin/pdf2txt'
+
+docconv_extractor_configuration:
+  docconv_path: '/usr/bin/docconv'
diff --git a/config/install/search_api_attachments.admin_config.yml b/config/install/search_api_attachments.admin_config.yml.orig
similarity index 100%
copy from config/install/search_api_attachments.admin_config.yml
copy to config/install/search_api_attachments.admin_config.yml.orig
diff --git a/src/Plugin/search_api/processor/FilesExtrator.php b/src/Plugin/search_api/processor/FilesExtrator.php
index 996ffa5..42ad1c4 100644
--- a/src/Plugin/search_api/processor/FilesExtrator.php
+++ b/src/Plugin/search_api/processor/FilesExtrator.php
@@ -6,17 +6,19 @@ use Drupal\Component\Utility\Bytes;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
 use Drupal\field\Entity\FieldConfig;
-use Drupal\Core\Form\FormStateInterface;
+use Drupal\file\Entity\File;
+use Drupal\search_api\Datasource\DatasourceInterface;
 use Drupal\search_api\Item\ItemInterface;
 use Drupal\search_api\Processor\ProcessorPluginBase;
-use Drupal\search_api\Datasource\DatasourceInterface;
+use Drupal\search_api\Processor\ProcessorProperty;
+use Drupal\search_api\Utility\FieldsHelperInterface;
 use Drupal\search_api_attachments\TextExtractorPluginInterface;
 use Drupal\search_api_attachments\TextExtractorPluginManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\search_api\Processor\ProcessorProperty;
-use Drupal\file\Entity\File;
 use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
 use Drupal\Core\Plugin\PluginFormInterface;
 
@@ -95,9 +97,16 @@ class FilesExtrator extends ProcessorPluginBase implements PluginFormInterface {
   protected $moduleHandler;
 
   /**
+   * Search API field helper.
+   *
+   * @var \Drupal\search_api\Utility\FieldsHelperInterface
+   */
+  protected $fieldHelper;
+
+  /**
    * {@inheritdoc}
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, TextExtractorPluginManager $text_extractor_plugin_manager, MimeTypeGuesserInterface $mime_type_guesser, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, KeyValueFactoryInterface $key_value, ModuleHandlerInterface $module_handler) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, TextExtractorPluginManager $text_extractor_plugin_manager, MimeTypeGuesserInterface $mime_type_guesser, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, KeyValueFactoryInterface $key_value, ModuleHandlerInterface $module_handler, FieldsHelperInterface $field_helper) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->textExtractorPluginManager = $text_extractor_plugin_manager;
     $this->mimeTypeGuesser = $mime_type_guesser;
@@ -105,6 +114,7 @@ class FilesExtrator extends ProcessorPluginBase implements PluginFormInterface {
     $this->entityTypeManager = $entity_type_manager;
     $this->keyValue = $key_value;
     $this->moduleHandler = $module_handler;
+    $this->fieldHelper = $field_helper;
   }
 
   /**
@@ -112,7 +122,7 @@ class FilesExtrator extends ProcessorPluginBase implements PluginFormInterface {
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
     return new static(
-        $configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.search_api_attachments.text_extractor'), $container->get('file.mime_type.guesser'), $container->get('config.factory'), $container->get('entity_type.manager'), $container->get('keyvalue'), $container->get('module_handler')
+        $configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.search_api_attachments.text_extractor'), $container->get('file.mime_type.guesser'), $container->get('config.factory'), $container->get('entity_type.manager'), $container->get('keyvalue'), $container->get('module_handler'), $container->get('search_api.fields_helper')
     );
   }
 
@@ -164,7 +174,7 @@ class FilesExtrator extends ProcessorPluginBase implements PluginFormInterface {
         $property_path = static::SAA_PREFIX . $field_name;
 
         // A way to load $field.
-        foreach ($this->getFieldsHelper()->filterForPropertyPath($item->getFields(), NULL, $property_path) as $field) {
+        foreach ($this->fieldHelper->filterForPropertyPath($item->getFields(), NULL, $property_path) as $field) {
           if ($entity->hasField($field_name)) {
             $filefield_values = $entity->get($field_name)->filterEmptyItems()->getValue();
 
@@ -364,9 +374,9 @@ class FilesExtrator extends ProcessorPluginBase implements PluginFormInterface {
         $file_elements[static::SAA_FILE_ENTITY] = $this->t('File entity');
       }
       foreach ($datasource->getPropertyDefinitions() as $property) {
-        if ($property instanceof FieldConfig) {
-          if ($property->get('field_type') == 'file') {
-            $file_elements[$property->get('field_name')] = $property->get('label');
+        if ($property instanceof FieldDefinitionInterface) {
+          if ($property->getType() == 'file') {
+            $file_elements[$property->getName()] = $property->getLabel();
           }
         }
       }
diff --git a/src/Plugin/search_api/processor/FilesExtrator.php b/src/Plugin/search_api/processor/FilesExtrator.php.orig
similarity index 100%
copy from src/Plugin/search_api/processor/FilesExtrator.php
copy to src/Plugin/search_api/processor/FilesExtrator.php.orig
diff --git a/src/Plugin/search_api_attachments/DocconvExtractor.php b/src/Plugin/search_api_attachments/DocconvExtractor.php
new file mode 100644
index 0000000..8d8b06d
--- /dev/null
+++ b/src/Plugin/search_api_attachments/DocconvExtractor.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Drupal\search_api_attachments\Plugin\search_api_attachments;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\file\Entity\File;
+use Drupal\search_api_attachments\TextExtractorPluginBase;
+
+/**
+ * Provides docconv extractor.
+ *
+ * @SearchApiAttachmentsTextExtractor(
+ *   id = "docconv_extractor",
+ *   label = @Translation("Docconv Extractor"),
+ *   description = @Translation("Adds Docconv extractor support."),
+ * )
+ */
+class DocconvExtractor extends TextExtractorPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extract(File $file) {
+    $docconv_path = $this->configuration['docconv_path'];
+    $filepath = $this->getRealpath($file->getFileUri());
+    $cmd = escapeshellarg($docconv_path) . ' -input ' . escapeshellarg($filepath);
+
+    // UTF-8 multibyte characters will be stripped by escapeshellargs() for
+    // the default C-locale.
+    // So temporarily set the locale to UTF-8 so that the filepath remains
+    // valid.
+    $backup_locale = setlocale(LC_CTYPE, '0');
+    setlocale(LC_CTYPE, $backup_locale);
+    // Support UTF-8 commands.
+    // @see http://www.php.net/manual/en/function.shell-exec.php#85095
+    shell_exec("LANG=en_US.utf-8");
+
+    return shell_exec($cmd);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form['docconv_path'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Full path to the docconv binary'),
+      '#description' => $this->t('Enter the full path to the docconv binary. Example: "/usr/bin/docconv".'),
+      '#default_value' => $this->configuration['docconv_path'],
+      '#required' => TRUE,
+    ];
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
+    $docconv_path = $form_state->getValue([
+      'text_extractor_config',
+      'docconv_path',
+    ]);
+    if (!file_exists($docconv_path) && isset($form['text_extractor_config']['docconv_path'])) {
+      $form_state->setError($form['text_extractor_config']['docconv_path'], $this->t('The file %path does not exist.', ['%path' => $docconv_path]));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    $this->configuration['docconv_path'] = $form_state->getValue([
+      'text_extractor_config',
+      'docconv_path',
+    ]);
+    parent::submitConfigurationForm($form, $form_state);
+  }
+
+}
