diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 71b5906e03a7ae33b1810f34b368fb03931d90c8..e951a96e6f7f14fa085521a552c3a1ff0ed8d2bb 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -627,9 +627,26 @@ database          = mysql://root@localhost/vufind
 ;coversize = false
 
 ; You can select Syndetics, LibraryThing, Summon, Amazon, Booksite, OpenLibrary,
-; Contentcafe, Buchhandel.de and/or Google Books.
+; Contentcafe, Buchhandel.de, Google Books, and/or LocalFile.
 ;   Note: Summon service takes a Serials Solutions client key, NOT Summon API key!
-;coverimages     = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID
+;   For LocalFile:PathToFile, you may use a combination of directory path information
+;        and tokens for filename and image type. If you have multiple directories
+;        in which you have stored coverimages, you can specify multiple paths to search
+;        by specifying multiple LocalFile:PathToFile in the coverage images list below.
+;        Allowed tokens:
+;          %anyimage%         - Match known image file extensions (gif, jpg, etc.)
+;          %isbn10%           - 10-digit ISBN
+;          %isbn13%           - 13-digit ISBN
+;          %issn%             - ISSN
+;          %oclc%             - OCLC Number
+;          %recordid%         - Bibliographic record ID
+;          %size%             - Size (small/medium/large)
+;          %source%           - Search backend of record (e.g. Summon, Solr, etc.)
+;          %upc%              - UPC Number
+;          %vufind-home%      - The VUFIND_HOME environment variable
+;          %vufind-local-dir% - The VUFIND_LOCAL_DIR environment variable
+;        Example: LocalFile:%vufind-local-dir%/path/to/file/%size%/issn/%issn%.%anyimage%
+;coverimages     = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,LocalFile:PathToFile
 
 ; This setting controls which services will have images cached on your local disk.
 ; Set to true to cache all applicable services. Set to false to disable caching. Set
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 28daf7cf626083b7f054d5f6c30c912531583f08..6c9668bbcf7afc6ab4bb3e997268e295f3550e14 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -372,6 +372,7 @@ $config = [
                 'invokables' => [
                     'google' => 'VuFind\Content\Covers\Google',
                     'librarything' => 'VuFind\Content\Covers\LibraryThing',
+                    'localfile' => 'VuFind\Content\Covers\LocalFile',
                     'openlibrary' => 'VuFind\Content\Covers\OpenLibrary',
                     'summon' => 'VuFind\Content\Covers\Summon',
                 ],
diff --git a/module/VuFind/src/VuFind/Content/Covers/LocalFile.php b/module/VuFind/src/VuFind/Content/Covers/LocalFile.php
new file mode 100644
index 0000000000000000000000000000000000000000..94d5c30e5b89bc16a4b0b7f890f555fd73cb2de5
--- /dev/null
+++ b/module/VuFind/src/VuFind/Content/Covers/LocalFile.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * LocalFile cover content loader.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Content
+ * @author   Leila Gonzales <lmg@agiweb.org>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Content\Covers;
+
+/**
+ * Local file cover content loader.
+ *
+ * @category VuFind
+ * @package  Content
+ * @author   Leila Gonzales <lmg@agiweb.org>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class LocalFile extends \VuFind\Content\AbstractCover
+{
+    /**
+     * Image file extensions to look for when using %anyimage% token.
+     *
+     * @var array
+     */
+    protected $imageExtensions = ["gif", "jpg", "jpeg", "png", "tif", "tiff"];
+
+    /**
+     * MIME types allowed to be loaded from disk.
+     *
+     * @var array
+     */
+    protected $allowedMimeTypes = [
+        "image/gif", "image/jpeg", "image/png", "image/tiff"
+    ];
+
+    /**
+     * Does this plugin support the provided ID array?
+     *
+     * @param array $ids IDs that will later be sent to load() -- see below.
+     *
+     * @return bool
+     */
+    public function supports($ids)
+    {
+        // We won't know what we need until we parse the path string; accept
+        // everything at this stage:
+        return true;
+    }
+
+    /**
+     * Get image location from local file storage.
+     *
+     * @param string $key  local file directory path
+     * @param string $size Size of image to load (small/medium/large)
+     * @param array  $ids  Associative array of identifiers (keys may include 'isbn'
+     * pointing to an ISBN object and 'issn' pointing to a string)
+     *
+     * @return string|bool
+     */
+    public function getUrl($key, $size, $ids)
+    {
+        // convert all of the tokens:
+        $fileName = $this->replaceImageTypeTokens(
+            $this->replaceEnvironmentAndIdTokens($key, $ids)
+        );
+        // Validate MIME type if we have a valid file path.
+        if ($fileName && file_exists($fileName)) {
+            if (in_array(mime_content_type($fileName), $this->allowedMimeTypes)) {
+                return "file://" . $fileName;
+            }
+        }
+        // If we got this far, we couldn't find a match.
+        return false;
+    }
+
+    /**
+     * Convert tokens to ids array values.
+     *
+     * @param string $filePath file path of image file
+     * @param array  $ids      Associative array of identifiers
+     * (keys may include 'isbn' pointing to an ISBN object and
+     * 'issn' pointing to a string)
+     *
+     * @return string
+     */
+    protected function replaceEnvironmentAndIdTokens($filePath, $ids)
+    {
+        // Seed the token array with standard environment variables:
+        $tokens = ['%vufind-home%', '%vufind-local-dir%'];
+        $replacements = [APPLICATION_PATH, LOCAL_OVERRIDE_DIR];
+
+        // Only create tokens for strings, not objects:
+        foreach ($ids as $key => $val) {
+            if (is_string($val)) {
+                $tokens[] = '%' . $key . '%';
+                $replacements[] = $val;
+            }
+        }
+        // Special-case handling for ISBN object:
+        if (isset($ids['isbn'])) {
+            $tokens[] = '%isbn10%';
+            $replacements[] = $ids['isbn']->get10();
+
+            $tokens[] = '%isbn13%';
+            $replacements[] = $ids['isbn']->get13();
+        }
+        return str_replace($tokens, $replacements, $filePath);
+    }
+
+    /**
+     * Convert tokens to image type file extension.
+     *
+     * @param string $fileName file path of image file
+     *
+     * @return bool|string
+     */
+    protected function replaceImageTypeTokens($fileName)
+    {
+        // If anyimage is specified, then we loop through all
+        // image extensions to find the right filename
+        if (strstr($fileName, '%anyimage%')) {
+            foreach ($this->imageExtensions as $val) {
+                foreach ([$val, strtoupper($val), ucwords($val)] as $finalVal) {
+                    $checkFile = str_replace('%anyimage%', $finalVal, $fileName);
+                    if (file_exists($checkFile)) {
+                         return $checkFile;
+                    }
+                }
+            }
+        }
+        // Default behavior: do not modify filename:
+        return $fileName;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/CoverController.php b/module/VuFind/src/VuFind/Controller/CoverController.php
index 9c387fb605c88e9f8f900f95670c91cc0d2d6b37..9284ca2b3e32bf4f5702560b8f22041f8b0d8ae1 100644
--- a/module/VuFind/src/VuFind/Controller/CoverController.php
+++ b/module/VuFind/src/VuFind/Controller/CoverController.php
@@ -125,6 +125,8 @@ class CoverController extends AbstractBase
             'issn' => $params()->fromQuery('issn'),
             'oclc' => $params()->fromQuery('oclc'),
             'upc' => $params()->fromQuery('upc'),
+            'recordid' => $params()->fromQuery('recordid'),
+            'source' => $params()->fromQuery('source'),
         ];
     }
 
diff --git a/module/VuFind/src/VuFind/Cover/Loader.php b/module/VuFind/src/VuFind/Cover/Loader.php
index 28c4477cb7dfc8f42aedee3d345ad58187492cc9..b48675e37acc770538c9e7941a5d794017f6d723 100644
--- a/module/VuFind/src/VuFind/Cover/Loader.php
+++ b/module/VuFind/src/VuFind/Cover/Loader.php
@@ -111,6 +111,20 @@ class Loader extends \VuFind\ImageLoader
      */
     protected $upc = null;
 
+    /**
+     * User record id number parameter
+     *
+     * @var string
+     */
+    protected $recordid = null;
+
+    /**
+     * User record source parameter
+     *
+     * @var string
+     */
+    protected $source = null;
+
     /**
      * User size parameter
      *
@@ -209,6 +223,8 @@ class Loader extends \VuFind\ImageLoader
             'issn' => null,
             'oclc' => null,
             'upc' => null,
+            'recordid' => null,
+            'source' => null,
         ];
     }
 
@@ -253,6 +269,8 @@ class Loader extends \VuFind\ImageLoader
         }
         $this->oclc = $settings['oclc'];
         $this->upc = $settings['upc'];
+        $this->recordid = $settings['recordid'];
+        $this->source = $settings['source'];
         $this->type = preg_replace('/[^a-zA-Z]/', '', $settings['type']);
         $this->size = $settings['size'];
     }
@@ -321,8 +339,13 @@ class Loader extends \VuFind\ImageLoader
             return $this->getCachePath($this->size, 'OCLC' . $ids['oclc']);
         } else if (isset($ids['upc'])) {
             return $this->getCachePath($this->size, 'UPC' . $ids['upc']);
+        } else if (isset($ids['recordid']) && isset($ids['source'])) {
+            return $this->getCachePath(
+                $this->size,
+                'ID' . md5($ids['source'] . '|' . $ids['recordid'])
+            );
         }
-        throw new \Exception('Unexpected code path reached!');
+        throw new \Exception('Cannot determine local file path.');
     }
 
     /**
@@ -345,6 +368,12 @@ class Loader extends \VuFind\ImageLoader
         if ($this->upc && strlen($this->upc) > 0) {
             $ids['upc'] = $this->upc;
         }
+        if ($this->recordid && strlen($this->recordid) > 0) {
+            $ids['recordid'] = $this->recordid;
+        }
+        if ($this->source && strlen($this->source) > 0) {
+            $ids['source'] = $this->source;
+        }
         return $ids;
     }
 
@@ -557,44 +586,52 @@ class Loader extends \VuFind\ImageLoader
      */
     protected function processImageURL($url, $cache = true)
     {
-        // Attempt to pull down the image:
-        $result = $this->client->setUri($url)->send();
-        if (!$result->isSuccess()) {
-            $this->debug("Failed to retrieve image from " + $url);
-            return false;
-        }
+        // Check to see if url is a file path
+        if (substr($url, 0, 7) == "file://") {
+            $imagePath = substr($url, 7);
 
-        $image = $result->getBody();
+            // Display the image:
+            $this->contentType =  mime_content_type($imagePath);
+            $this->image = file_get_contents($imagePath);
+            return true;
+        } else {
+            // Attempt to pull down the image:
+            $result = $this->client->setUri($url)->send();
+            if (!$result->isSuccess()) {
+                $this->debug("Failed to retrieve image from " + $url);
+                return false;
+            }
+            $image = $result->getBody();
 
-        if ('' == $image) {
-            return false;
-        }
+            if ('' == $image) {
+                return false;
+            }
 
-        // Figure out file paths -- $tempFile will be used to store the
-        // image for analysis.  $finalFile will be used for long-term storage if
-        // $cache is true or for temporary display purposes if $cache is false.
-        $tempFile = str_replace('.jpg', uniqid(), $this->localFile);
-        $finalFile = $cache ? $this->localFile : $tempFile . '.jpg';
+            // Figure out file paths -- $tempFile will be used to store the
+            // image for analysis.  $finalFile will be used for long-term storage if
+            // $cache is true or for temporary display purposes if $cache is false.
+            $tempFile = str_replace('.jpg', uniqid(), $this->localFile);
+            $finalFile = $cache ? $this->localFile : $tempFile . '.jpg';
 
-        // Write image data to disk:
-        if (!@file_put_contents($tempFile, $image)) {
-            throw new \Exception("Unable to write to image directory.");
-        }
+            // Write image data to disk:
+            if (!@file_put_contents($tempFile, $image)) {
+                throw new \Exception("Unable to write to image directory.");
+            }
 
-        // Move temporary file to final location:
-        if (!$this->validateAndMoveTempFile($image, $tempFile, $finalFile)) {
-            return false;
-        }
+            // Move temporary file to final location:
+            if (!$this->validateAndMoveTempFile($image, $tempFile, $finalFile)) {
+                return false;
+            }
 
-        // Display the image:
-        $this->contentType = 'image/jpeg';
-        $this->image = file_get_contents($finalFile);
+            // Display the image:
+            $this->contentType = 'image/jpeg';
+            $this->image = file_get_contents($finalFile);
 
-        // If we don't want to cache the image, delete it now that we're done.
-        if (!$cache) {
-            @unlink($finalFile);
+            // If we don't want to cache the image, delete it now that we're done.
+            if (!$cache) {
+                @unlink($finalFile);
+            }
+            return true;
         }
-
-        return true;
     }
 }
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
index 361f0cfe46065676a70ad77ea12ac4d52d210e12..688a6c7d5f1017e73ae306926821aa78aa207bdb 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
@@ -1349,7 +1349,9 @@ class SolrDefault extends AbstractBase
             'author'     => mb_substr($this->getPrimaryAuthor(), 0, 300, 'utf-8'),
             'callnumber' => $this->getCallNumber(),
             'size'       => $size,
-            'title'      => mb_substr($this->getTitle(), 0, 300, 'utf-8')
+            'title'      => mb_substr($this->getTitle(), 0, 300, 'utf-8'),
+            'recordid'   => $this->getUniqueID(),
+            'source'   => $this->getSourceIdentifier(),
         ];
         if ($isbn = $this->getCleanISBN()) {
             $arr['isbn'] = $isbn;