diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php
index c25dc92409f04e890750d086fa9c5c86a05e6532..377c9f022536b4899bd4f7fb83cd79a9383c2b96 100644
--- a/apps/files_sharing/lib/cache.php
+++ b/apps/files_sharing/lib/cache.php
@@ -47,6 +47,7 @@ class Shared_Cache extends Cache {
 	 * @param \OC\Files\Storage\Shared $storage
 	 */
 	public function __construct($storage) {
+		parent::__construct($storage);
 		$this->storage = $storage;
 	}
 
@@ -94,6 +95,7 @@ class Shared_Cache extends Cache {
 	 * @return array|false
 	 */
 	public function get($file) {
+		$mimetypeLoader = \OC::$server->getMimeTypeLoader();
 		if (is_string($file)) {
 			$cache = $this->getSourceCache($file);
 			if ($cache) {
@@ -130,8 +132,8 @@ class Shared_Cache extends Cache {
 			$data['mtime'] = (int)$data['mtime'];
 			$data['storage_mtime'] = (int)$data['storage_mtime'];
 			$data['encrypted'] = (bool)$data['encrypted'];
-			$data['mimetype'] = $this->getMimetype($data['mimetype']);
-			$data['mimepart'] = $this->getMimetype($data['mimepart']);
+			$data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']);
+			$data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']);
 			if ($data['storage_mtime'] === 0) {
 				$data['storage_mtime'] = $data['mtime'];
 			}
diff --git a/core/command/maintenance/mimetype/updatedb.php b/core/command/maintenance/mimetype/updatedb.php
new file mode 100644
index 0000000000000000000000000000000000000000..37c401c0338cb8c0662d25e56aa0b3ed7bec2acb
--- /dev/null
+++ b/core/command/maintenance/mimetype/updatedb.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+namespace OC\Core\Command\Maintenance\Mimetype;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputOption;
+
+use OCP\Files\IMimeTypeDetector;
+use OCP\Files\IMimeTypeLoader;
+
+class UpdateDB extends Command {
+
+	const DEFAULT_MIMETYPE = 'application/octet-stream';
+
+	/** @var IMimeTypeDetector */
+	protected $mimetypeDetector;
+
+	/** @var IMimeTypeLoader */
+	protected $mimetypeLoader;
+
+	public function __construct(
+		IMimeTypeDetector $mimetypeDetector,
+		IMimeTypeLoader $mimetypeLoader
+	) {
+		parent::__construct();
+		$this->mimetypeDetector = $mimetypeDetector;
+		$this->mimetypeLoader = $mimetypeLoader;
+	}
+
+	protected function configure() {
+		$this
+			->setName('maintenance:mimetype:update-db')
+			->setDescription('Update database mimetypes and update filecache')
+			->addOption(
+				'repair-filecache',
+				null,
+				InputOption::VALUE_NONE,
+				'Repair filecache for all mimetypes, not just new ones'
+			)
+		;
+	}
+
+	protected function execute(InputInterface $input, OutputInterface $output) {
+		$mappings = $this->mimetypeDetector->getAllMappings();
+
+		$totalFilecacheUpdates = 0;
+		$totalNewMimetypes = 0;
+
+		foreach ($mappings as $ext => $mimetypes) {
+			if ($ext[0] === '_') {
+				// comment
+				continue;
+			}
+			$mimetype = $mimetypes[0];
+			$existing = $this->mimetypeLoader->exists($mimetype);
+			// this will add the mimetype if it didn't exist
+			$mimetypeId = $this->mimetypeLoader->getId($mimetype);
+
+			if (!$existing) {
+				$output->writeln('Added mimetype "'.$mimetype.'" to database');
+				$totalNewMimetypes++;
+			}
+
+			if (!$existing || $input->getOption('repair-filecache')) {
+				$touchedFilecacheRows = $this->mimetypeLoader->updateFilecache($ext, $mimetypeId);
+				if ($touchedFilecacheRows > 0) {
+					$output->writeln('Updated '.$touchedFilecacheRows.' filecache rows for mimetype "'.$mimetype.'"');
+				}
+				$totalFilecacheUpdates += $touchedFilecacheRows;
+			}
+		}
+
+		$output->writeln('Added '.$totalNewMimetypes.' new mimetypes');
+		$output->writeln('Updated '.$totalFilecacheUpdates.' filecache rows');
+	}
+}
diff --git a/core/command/maintenance/mimetypesjs.php b/core/command/maintenance/mimetype/updatejs.php
similarity index 75%
rename from core/command/maintenance/mimetypesjs.php
rename to core/command/maintenance/mimetype/updatejs.php
index 8b01f0acf79adcf79f8140e0ca444788905c10e7..5de75d53a3f13e898b0a5d099258de4a0a93b30a 100644
--- a/core/command/maintenance/mimetypesjs.php
+++ b/core/command/maintenance/mimetype/updatejs.php
@@ -18,27 +18,35 @@
  *
  */
 
-namespace OC\Core\Command\Maintenance;
+namespace OC\Core\Command\Maintenance\Mimetype;
 
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class MimeTypesJS extends Command {
+use OCP\Files\IMimeTypeDetector;
+
+class UpdateJS extends Command {
+
+	/** @var IMimeTypeDetector */
+	protected $mimetypeDetector;
+
+	public function __construct(
+		IMimeTypeDetector $mimetypeDetector
+	) {
+		parent::__construct();
+		$this->mimetypeDetector = $mimetypeDetector;
+	}
+
 	protected function configure() {
 		$this
-			->setName('maintenance:mimetypesjs')
+			->setName('maintenance:mimetype:update-js')
 			->setDescription('Update mimetypelist.js');
 	}
 
 	protected function execute(InputInterface $input, OutputInterface $output) {
 		// Fetch all the aliases
-		$aliases = json_decode(file_get_contents(\OC::$SERVERROOT . '/config/mimetypealiases.dist.json'), true);
-
-		if (file_exists(\OC::$SERVERROOT . '/config/mimetypealiases.json')) {
-			$custom = get_object_vars(json_decode(file_get_contents(\OC::$SERVERROOT . '/config/mimetypealiases.json')));
-			$aliases = array_merge($aliases, $custom);
-		}
+		$aliases = $this->mimetypeDetector->getAllAliases();
 
 		// Remove comments
 		$keys = array_filter(array_keys($aliases), function($k) {
@@ -49,23 +57,22 @@ class MimeTypesJS extends Command {
 		}
 
 		// Fetch all files
-		$dir = new \DirectoryIterator(dirname(__DIR__) . '/../img/filetypes');
+		$dir = new \DirectoryIterator(\OC::$SERVERROOT.'/core/img/filetypes');
 
 		$files = [];
 		foreach($dir as $fileInfo) {
-		    if ($fileInfo->isFile()) {
-        		$file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename());
-		        $files[] = $file;
-		    }  
+			if ($fileInfo->isFile()) {
+				$file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename());
+				$files[] = $file;
+			}
 		}
 
 		//Remove duplicates
 		$files = array_values(array_unique($files));
 
-
 		// Fetch all themes!
 		$themes = [];
-		$dirs = new \DirectoryIterator(dirname(__DIR__) . '/../../themes/');
+		$dirs = new \DirectoryIterator(\OC::$SERVERROOT.'/themes/');
 		foreach($dirs as $dir) {
 			//Valid theme dir
 			if ($dir->isFile() || $dir->isDot()) {
@@ -84,7 +91,7 @@ class MimeTypesJS extends Command {
 			$themeIt = new \DirectoryIterator($themeDir);
 			foreach ($themeIt as $fileInfo) {
 				if ($fileInfo->isFile()) {
- 		       		$file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename());
+					$file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename());
 					$themes[$theme][] = $file;
 				}
 			}
@@ -110,7 +117,7 @@ OC.MimeTypeList={
 ';
 
 		//Output the JS
-		file_put_contents(dirname(__DIR__) . '/../js/mimetypelist.js', $js);
+		file_put_contents(\OC::$SERVERROOT.'/core/js/mimetypelist.js', $js);
 
 		$output->writeln('<info>mimetypelist.js is updated');
 	}
diff --git a/core/register_command.php b/core/register_command.php
index 72c7b28e9aeea12b499e731030b4eaa708d4d91c..d3c04ad0671e57f9a29567ca949213bdca81a6b9 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -79,7 +79,8 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
 	);
 	$application->add(new OC\Core\Command\Encryption\ShowKeyStorageRoot($util));
 
-	$application->add(new OC\Core\Command\Maintenance\MimeTypesJS());
+	$application->add(new OC\Core\Command\Maintenance\Mimetype\UpdateDB(\OC::$server->getMimeTypeDetector(), \OC::$server->getMimeTypeLoader()));
+	$application->add(new OC\Core\Command\Maintenance\Mimetype\UpdateJS(\OC::$server->getMimeTypeDetector()));
 	$application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig()));
 	$application->add(new OC\Core\Command\Maintenance\Repair(new \OC\Repair(\OC\Repair::getRepairSteps()), \OC::$server->getConfig()));
 	$application->add(new OC\Core\Command\Maintenance\SingleUser(\OC::$server->getConfig()));
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index 8cf097421d4733bb36501b06dd5da9e344e2e91a..5c04da1f0d50a365fb9e65c1828ea68ea356874e 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -35,6 +35,8 @@
 
 namespace OC\Files\Cache;
 
+use \OCP\Files\IMimeTypeLoader;
+
 /**
  * Metadata cache for a storage
  *
@@ -66,8 +68,8 @@ class Cache {
 	 */
 	protected $storageCache;
 
-	protected static $mimetypeIds = array();
-	protected static $mimetypes = array();
+	/** @var IMimeTypeLoader */
+	protected $mimetypeLoader;
 
 	/**
 	 * @param \OC\Files\Storage\Storage|string $storage
@@ -83,6 +85,7 @@ class Cache {
 		}
 
 		$this->storageCache = new Storage($storage);
+		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
 	}
 
 	/**
@@ -94,72 +97,6 @@ class Cache {
 		return $this->storageCache->getNumericId();
 	}
 
-	/**
-	 * Get the numeric id for a mimetype
-	 *
-	 * Mimetypes are stored as integers in the cache to prevent duplicated data of the (usually) fairly limited amount of unique mimetypes
-	 * If the supplied mimetype does not yet have a numeric id a new one will be generated
-	 *
-	 * @param string $mime
-	 * @return int
-	 */
-	public function getMimetypeId($mime) {
-		if (empty($mime)) {
-			// Can not insert empty string into Oracle NOT NULL column.
-			$mime = 'application/octet-stream';
-		}
-		if (empty(self::$mimetypeIds)) {
-			$this->loadMimetypes();
-		}
-
-		if (!isset(self::$mimetypeIds[$mime])) {
-			try {
-				$connection = \OC_DB::getConnection();
-				$connection->insertIfNotExist('*PREFIX*mimetypes', [
-					'mimetype'	=> $mime,
-				]);
-				$this->loadMimetypes();
-			} catch (\Doctrine\DBAL\DBALException $e) {
-				\OCP\Util::writeLog('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OCP\Util::DEBUG);
-				return -1;
-			}
-		}
-
-		return self::$mimetypeIds[$mime];
-	}
-
-
-	/**
-	 * Get the mimetype (as string) from a mimetype id
-	 *
-	 * @param int $id
-	 * @return string | null the mimetype for the id or null if the id is not known
-	 */
-	public function getMimetype($id) {
-		if (empty(self::$mimetypes)) {
-			$this->loadMimetypes();
-		}
-
-		return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null;
-	}
-
-	/**
-	 * Load all known mimetypes and mimetype ids from the database
-	 *
-	 * @throws \OC\DatabaseException
-	 */
-	public function loadMimetypes() {
-		self::$mimetypeIds = self::$mimetypes = array();
-
-		$result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array());
-		if ($result) {
-			while ($row = $result->fetchRow()) {
-				self::$mimetypeIds[$row['mimetype']] = $row['id'];
-				self::$mimetypes[$row['id']] = $row['mimetype'];
-			}
-		}
-	}
-
 	/**
 	 * get the stored metadata of a file or folder
 	 *
@@ -222,8 +159,8 @@ class Cache {
 			$data['storage_mtime'] = (int)$data['storage_mtime'];
 			$data['encrypted'] = (bool)$data['encrypted'];
 			$data['storage'] = $this->storageId;
-			$data['mimetype'] = $this->getMimetype($data['mimetype']);
-			$data['mimepart'] = $this->getMimetype($data['mimepart']);
+			$data['mimetype'] = $this->mimetypeLoader->getMimetypeById($data['mimetype']);
+			$data['mimepart'] = $this->mimetypeLoader->getMimetypeById($data['mimepart']);
 			if ($data['storage_mtime'] == 0) {
 				$data['storage_mtime'] = $data['mtime'];
 			}
@@ -258,8 +195,8 @@ class Cache {
 			$result = \OC_DB::executeAudited($sql, array($fileId));
 			$files = $result->fetchAll();
 			foreach ($files as &$file) {
-				$file['mimetype'] = $this->getMimetype($file['mimetype']);
-				$file['mimepart'] = $this->getMimetype($file['mimepart']);
+				$file['mimetype'] = $this->mimetypeLoader->getMimetypeById($file['mimetype']);
+				$file['mimepart'] = $this->mimetypeLoader->getMimetypeById($file['mimepart']);
 				if ($file['storage_mtime'] == 0) {
 					$file['storage_mtime'] = $file['mtime'];
 				}
@@ -385,9 +322,9 @@ class Cache {
 					$params[] = md5($value);
 					$queryParts[] = '`path_hash`';
 				} elseif ($name === 'mimetype') {
-					$params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/')));
+					$params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
 					$queryParts[] = '`mimepart`';
-					$value = $this->getMimetypeId($value);
+					$value = $this->mimetypeLoader->getId($value);
 				} elseif ($name === 'storage_mtime') {
 					if (!isset($data['mtime'])) {
 						$params[] = $value;
@@ -613,7 +550,6 @@ class Cache {
 	 * @return array an array of cache entries where the name matches the search pattern
 	 */
 	public function search($pattern) {
-
 		// normalize pattern
 		$pattern = $this->normalize($pattern);
 
@@ -630,8 +566,8 @@ class Cache {
 
 		$files = array();
 		while ($row = $result->fetchRow()) {
-			$row['mimetype'] = $this->getMimetype($row['mimetype']);
-			$row['mimepart'] = $this->getMimetype($row['mimepart']);
+			$row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']);
+			$row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']);
 			$files[] = $row;
 		}
 		return $files;
@@ -652,12 +588,12 @@ class Cache {
 		}
 		$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`, `permissions`
 				FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?';
-		$mimetype = $this->getMimetypeId($mimetype);
+		$mimetype = $this->mimetypeLoader->getId($mimetype);
 		$result = \OC_DB::executeAudited($sql, array($mimetype, $this->getNumericStorageId()));
 		$files = array();
 		while ($row = $result->fetchRow()) {
-			$row['mimetype'] = $this->getMimetype($row['mimetype']);
-			$row['mimepart'] = $this->getMimetype($row['mimepart']);
+			$row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']);
+			$row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']);
 			$files[] = $row;
 		}
 		return $files;
diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php
index ba286637df38ba8043f701d55366eaee85017d67..3dc3975fb2afa914f8a6ccab9422512dff8fac7f 100644
--- a/lib/private/files/type/detection.php
+++ b/lib/private/files/type/detection.php
@@ -6,6 +6,7 @@
  * @author Robin Appelman <icewind@owncloud.com>
  * @author Roeland Jago Douma <roeland@famdouma.nl>
  * @author Thomas Tanghus <thomas@tanghus.net>
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
  *
  * @copyright Copyright (c) 2015, ownCloud, Inc.
  * @license AGPL-3.0
@@ -101,15 +102,22 @@ class Detection implements IMimeTypeDetector {
 			return;
 		}
 
-		$file = file_get_contents($this->configDir . '/mimetypealiases.dist.json');
-		$this->mimeTypeAlias = get_object_vars(json_decode($file));
+		$this->mimeTypeAlias = json_decode(file_get_contents($this->configDir . '/mimetypealiases.dist.json'), true);
 
 		if (file_exists($this->configDir . '/mimetypealiases.json')) {
-			$custom = get_object_vars(json_decode(file_get_contents($this->configDir . '/mimetypealiases.json')));
+			$custom = json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'), true);
 			$this->mimeTypeAlias = array_merge($this->mimeTypeAlias, $custom);
 		}
 	}
 
+	/**
+	 * @return array
+	 */
+	public function getAllAliases() {
+		$this->loadAliases();
+		return $this->mimeTypeAlias;
+	}
+
 	/**
 	 * Add mimetype mappings if they are not yet present
 	 */
@@ -118,19 +126,25 @@ class Detection implements IMimeTypeDetector {
 			return;
 		}
 
-		$dist = file_get_contents($this->configDir . '/mimetypemapping.dist.json');
-		$mimetypemapping = get_object_vars(json_decode($dist));
+		$mimetypemapping = json_decode(file_get_contents($this->configDir . '/mimetypemapping.dist.json'), true);
 
 		//Check if need to load custom mappings
 		if (file_exists($this->configDir . '/mimetypemapping.json')) {
-			$custom = file_get_contents($this->configDir . '/mimetypemapping.json');
-			$custom_mapping = get_object_vars(json_decode($custom));
-			$mimetypemapping = array_merge($mimetypemapping, $custom_mapping);
+			$custom = json_decode(file_get_contents($this->configDir . '/mimetypemapping.json'), true);
+			$mimetypemapping = array_merge($mimetypemapping, $custom);
 		}
 
 		$this->registerTypeArray($mimetypemapping);
 	}
 
+	/**
+	 * @return array
+	 */
+	public function getAllMappings() {
+		$this->loadMappings();
+		return $this->mimetypes;
+	}
+
 	/**
 	 * detect mimetype only based on filename, content of file is not used
 	 *
diff --git a/lib/private/files/type/loader.php b/lib/private/files/type/loader.php
new file mode 100644
index 0000000000000000000000000000000000000000..df893306615d9797681cdf71c75785cbb72dcb2d
--- /dev/null
+++ b/lib/private/files/type/loader.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Type;
+
+use OCP\Files\IMimeTypeLoader;
+use OCP\IDBConnection;
+
+use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+
+/**
+ * Mimetype database loader
+ *
+ * @package OC\Files\Type
+ */
+class Loader implements IMimeTypeLoader {
+
+	/** @var IDBConnection */
+	private $dbConnection;
+
+	/** @var array [id => mimetype] */
+	protected $mimetypes;
+
+	/** @var array [mimetype => id] */
+	protected $mimetypeIds;
+
+	/**
+	 * @param IDBConnection $dbConnection
+	 */
+	public function __construct(IDBConnection $dbConnection) {
+		$this->dbConnection = $dbConnection;
+		$this->mimetypes = [];
+		$this->mimetypeIds = [];
+	}
+
+	/**
+	 * Get a mimetype from its ID
+	 *
+	 * @param int $id
+	 * @return string|null
+	 */
+	public function getMimetypeById($id) {
+		if (!$this->mimetypes) {
+			$this->loadMimetypes();
+		}
+		if (isset($this->mimetypes[$id])) {
+			return $this->mimetypes[$id];
+		}
+		return null;
+	}
+
+	/**
+	 * Get a mimetype ID, adding the mimetype to the DB if it does not exist
+	 *
+	 * @param string $mimetype
+	 * @return int
+	 */
+	public function getId($mimetype) {
+		if (!$this->mimetypeIds) {
+			$this->loadMimetypes();
+		}
+		if (isset($this->mimetypeIds[$mimetype])) {
+			return $this->mimetypeIds[$mimetype];
+		}
+		return $this->store($mimetype);
+	}
+
+	/**
+	 * Test if a mimetype exists in the database
+	 *
+	 * @param string $mimetype
+	 * @return bool
+	 */
+	public function exists($mimetype) {
+		if (!$this->mimetypeIds) {
+			$this->loadMimetypes();
+		}
+		return isset($this->mimetypeIds[$mimetype]);
+	}
+
+	/**
+	 * Store a mimetype in the DB
+	 *
+	 * @param string $mimetype
+	 * @param int inserted ID
+	 */
+	protected function store($mimetype) {
+		try {
+			$qb = $this->dbConnection->getQueryBuilder();
+			$qb->insert('mimetypes')
+				->values([
+					'mimetype' => $qb->createNamedParameter($mimetype)
+				]);
+			$qb->execute();
+		} catch (UniqueConstraintViolationException $e) {
+			// something inserted it before us
+		}
+
+		$fetch = $this->dbConnection->getQueryBuilder();
+		$fetch->select('id')
+			->from('mimetypes')
+			->where(
+				$fetch->expr()->eq('mimetype', $fetch->createNamedParameter($mimetype)
+			));
+		$row = $fetch->execute()->fetch();
+
+		$this->mimetypes[$row['id']] = $mimetype;
+		$this->mimetypeIds[$mimetype] = $row['id'];
+		return $row['id'];
+	}
+
+	/**
+	 * Load all mimetypes from DB
+	 */
+	private function loadMimetypes() {
+		$qb = $this->dbConnection->getQueryBuilder();
+		$qb->select('id', 'mimetype')
+			->from('mimetypes');
+		$results = $qb->execute()->fetchAll();
+
+		foreach ($results as $row) {
+			$this->mimetypes[$row['id']] = $row['mimetype'];
+			$this->mimetypeIds[$row['mimetype']] = $row['id'];
+		}
+	}
+
+	/**
+	 * Update filecache mimetype based on file extension
+	 *
+	 * @param string $ext file extension
+	 * @param int $mimetypeId
+	 * @return int number of changed rows
+	 */
+	public function updateFilecache($ext, $mimetypeId) {
+		$update = $this->dbConnection->getQueryBuilder();
+		$update->update('filecache')
+			->set('mimetype', $update->createNamedParameter($mimetypeId))
+			->where($update->expr()->neq(
+				'mimetype', $update->createNamedParameter($mimetypeId)
+			))
+			->andWhere($update->expr()->like(
+				$update->createFunction('LOWER(`name`)'), $update->createNamedParameter($ext)
+			));
+		return $update->execute();
+	}
+
+}
diff --git a/lib/private/server.php b/lib/private/server.php
index 24674d2e3c73023ae74e01327ba67f5b5b2ef534..393c1840973ce6c73177c73aa33f25c7bb05bd2c 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -470,6 +470,11 @@ class Server extends SimpleContainer implements IServerContainer {
 				$c->getURLGenerator(),
 				\OC::$configDir);
 		});
+		$this->registerService('MimeTypeLoader', function(Server $c) {
+			return new \OC\Files\Type\Loader(
+				$c->getDatabaseConnection()
+			);
+		});
 		$this->registerService('CapabilitiesManager', function (Server $c) {
 			$manager = new \OC\CapabilitiesManager();
 			$manager->registerCapability(function() use ($c) {
@@ -1010,6 +1015,15 @@ class Server extends SimpleContainer implements IServerContainer {
 		return $this->query('MimeTypeDetector');
 	}
 
+	/**
+	 * Get the MimeTypeLoader
+	 *
+	 * @return \OCP\Files\IMimeTypeLoader
+	 */
+	public function getMimeTypeLoader() {
+		return $this->query('MimeTypeLoader');
+	}
+
 	/**
 	 * Get the manager of all the capabilities
 	 *
diff --git a/lib/public/files/imimetypeloader.php b/lib/public/files/imimetypeloader.php
new file mode 100644
index 0000000000000000000000000000000000000000..24937ea9b860ead82caa707d34bd42313dffce16
--- /dev/null
+++ b/lib/public/files/imimetypeloader.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files;
+
+/**
+ * Interface IMimeTypeLoader
+ * @package OCP\Files
+ * @since 8.2.0
+ *
+ * Interface to load mimetypes
+ **/
+interface IMimeTypeLoader {
+
+	/**
+	 * Get a mimetype from its ID
+	 *
+	 * @param int $id
+	 * @return string|null
+	 * @since 8.2.0
+	 */
+	public function getMimetypeById($id);
+
+	/**
+	 * Get a mimetype ID, adding the mimetype to the DB if it does not exist
+	 *
+	 * @param string $mimetype
+	 * @return int
+	 * @since 8.2.0
+	 */
+	public function getId($mimetype);
+
+	/**
+	 * Test if a mimetype exists in the database
+	 *
+	 * @param string $mimetype
+	 * @return bool
+	 * @since 8.2.0
+	 */
+	public function exists($mimetype);
+}
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
index a6d83156de3105a3d52b1b22a6b9aeb0d1ad5a21..81724cb4967b9ec3f44afcbd0f9811a0613dfd44 100644
--- a/lib/public/iservercontainer.php
+++ b/lib/public/iservercontainer.php
@@ -440,6 +440,14 @@ interface IServerContainer {
 	 */
 	public function getMimeTypeDetector();
 
+	/**
+	 * Get the MimeTypeLoader
+	 *
+	 * @return \OCP\Files\IMimeTypeLoader
+	 * @since 8.2.0
+	 */
+	public function getMimeTypeLoader();
+
 
 	/**
 	 * Get the EventDispatcher
diff --git a/tests/core/command/maintenance/mimetype/updatedbtest.php b/tests/core/command/maintenance/mimetype/updatedbtest.php
new file mode 100644
index 0000000000000000000000000000000000000000..217301102c5b89d2453347a97a0e2bf5c9826625
--- /dev/null
+++ b/tests/core/command/maintenance/mimetype/updatedbtest.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Tests\Core\Command\Maintenance\Mimetype;
+
+use OC\Core\Command\Maintenance\Mimetype\UpdateDB;
+use Test\TestCase;
+use OCP\Files\IMimeTypeDetector;
+use OCP\Files\IMimeTypeLoader;
+
+class UpdateDBTest extends TestCase {
+	/** @var IMimeTypeDetector */
+	protected $detector;
+	/** @var IMimeTypeLoader */
+	protected $loader;
+
+	/** @var \PHPUnit_Framework_MockObject_MockObject */
+	protected $consoleInput;
+	/** @var \PHPUnit_Framework_MockObject_MockObject */
+	protected $consoleOutput;
+
+	/** @var \Symfony\Component\Console\Command\Command */
+	protected $command;
+
+	protected function setUp() {
+		parent::setUp();
+
+		$this->detector = $this->getMockBuilder('OC\Files\Type\Detection')
+			->disableOriginalConstructor()
+			->getMock();
+		$this->loader = $this->getMockBuilder('OC\Files\Type\Loader')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+		$this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+		$this->command = new UpdateDB($this->detector, $this->loader);
+	}
+
+	public function testNoop() {
+		$this->consoleInput->method('getOption')
+			->with('repair-filecache')
+			->willReturn(false);
+
+		$this->detector->expects($this->once())
+			->method('getAllMappings')
+			->willReturn([
+				'ext' => ['testing/existingmimetype']
+			]);
+		$this->loader->expects($this->once())
+			->method('exists')
+			->with('testing/existingmimetype')
+			->willReturn(true);
+
+		$this->loader->expects($this->never())
+			->method('updateFilecache');
+
+		$this->consoleOutput->expects($this->at(0))
+			->method('writeln')
+			->with('Added 0 new mimetypes');
+		$this->consoleOutput->expects($this->at(1))
+			->method('writeln')
+			->with('Updated 0 filecache rows');
+
+		self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+	}
+
+	public function testAddMimetype() {
+		$this->consoleInput->method('getOption')
+			->with('repair-filecache')
+			->willReturn(false);
+
+		$this->detector->expects($this->once())
+			->method('getAllMappings')
+			->willReturn([
+				'ext' => ['testing/existingmimetype'],
+				'new' => ['testing/newmimetype']
+			]);
+		$this->loader->expects($this->exactly(2))
+			->method('exists')
+			->will($this->returnValueMap([
+				['testing/existingmimetype', true],
+				['testing/newmimetype', false],
+			]));
+		$this->loader->expects($this->exactly(2))
+			->method('getId')
+			->will($this->returnValueMap([
+				['testing/existingmimetype', 1],
+				['testing/newmimetype', 2],
+			]));
+
+		$this->loader->expects($this->once())
+			->method('updateFilecache')
+			->with('new', 2)
+			->willReturn(3);
+
+		$this->consoleOutput->expects($this->at(0))
+			->method('writeln')
+			->with('Added mimetype "testing/newmimetype" to database');
+		$this->consoleOutput->expects($this->at(1))
+			->method('writeln')
+			->with('Updated 3 filecache rows for mimetype "testing/newmimetype"');
+
+		$this->consoleOutput->expects($this->at(2))
+			->method('writeln')
+			->with('Added 1 new mimetypes');
+		$this->consoleOutput->expects($this->at(3))
+			->method('writeln')
+			->with('Updated 3 filecache rows');
+
+		self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+	}
+
+	public function testSkipComments() {
+		$this->detector->expects($this->once())
+			->method('getAllMappings')
+			->willReturn([
+				'_comment' => 'some comment in the JSON'
+			]);
+		$this->loader->expects($this->never())
+			->method('exists');
+
+		self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+	}
+
+	public function testRepairFilecache() {
+		$this->consoleInput->method('getOption')
+			->with('repair-filecache')
+			->willReturn(true);
+
+		$this->detector->expects($this->once())
+			->method('getAllMappings')
+			->willReturn([
+				'ext' => ['testing/existingmimetype'],
+			]);
+		$this->loader->expects($this->exactly(1))
+			->method('exists')
+			->will($this->returnValueMap([
+				['testing/existingmimetype', true],
+			]));
+		$this->loader->expects($this->exactly(1))
+			->method('getId')
+			->will($this->returnValueMap([
+				['testing/existingmimetype', 1],
+			]));
+
+		$this->loader->expects($this->once())
+			->method('updateFilecache')
+			->with('ext', 1)
+			->willReturn(3);
+
+		$this->consoleOutput->expects($this->at(0))
+			->method('writeln')
+			->with('Updated 3 filecache rows for mimetype "testing/existingmimetype"');
+
+		$this->consoleOutput->expects($this->at(1))
+			->method('writeln')
+			->with('Added 0 new mimetypes');
+		$this->consoleOutput->expects($this->at(2))
+			->method('writeln')
+			->with('Updated 3 filecache rows');
+
+		self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+	}
+}
diff --git a/tests/lib/files/type/loadertest.php b/tests/lib/files/type/loadertest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f87afd2f4d4e71b1cb4fbc895ab62e555a9ac57
--- /dev/null
+++ b/tests/lib/files/type/loadertest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Type;
+
+use \OC\Files\Type\Loader;
+use \OCP\IDBConnection;
+
+class LoaderTest extends \Test\TestCase {
+	/** @var IDBConnection */
+	protected $db;
+	/** @var Loader */
+	protected $loader;
+
+	protected function setUp() {
+		$this->db = \OC::$server->getDatabaseConnection();
+		$this->loader = new Loader($this->db);
+	}
+
+	protected function tearDown() {
+		$deleteMimetypes = $this->db->getQueryBuilder();
+		$deleteMimetypes->delete('mimetypes')
+			->where($deleteMimetypes->expr()->like(
+				'mimetype', $deleteMimetypes->createPositionalParameter('testing/%')
+			));
+		$deleteMimetypes->execute();
+	}
+
+
+	public function testGetMimetype() {
+		$qb = $this->db->getQueryBuilder();
+		$qb->insert('mimetypes')
+			->values([
+				'mimetype' => $qb->createPositionalParameter('testing/mymimetype')
+			]);
+		$qb->execute();
+
+		$this->assertTrue($this->loader->exists('testing/mymimetype'));
+		$mimetypeId = $this->loader->getId('testing/mymimetype');
+		$this->assertNotNull($mimetypeId);
+
+		$mimetype = $this->loader->getMimetypeById($mimetypeId);
+		$this->assertEquals('testing/mymimetype', $mimetype);
+	}
+
+	public function testGetNonexistentMimetype() {
+		$this->assertFalse($this->loader->exists('testing/nonexistent'));
+		// hopefully this ID doesn't exist
+		$this->assertNull($this->loader->getMimetypeById(12345));
+	}
+
+	public function testStore() {
+		$this->assertFalse($this->loader->exists('testing/mymimetype'));
+		$mimetypeId = $this->loader->getId('testing/mymimetype');
+
+		$qb = $this->db->getQueryBuilder();
+		$qb->select('mimetype')
+			->from('mimetypes')
+			->where($qb->expr()->eq('id', $qb->createPositionalParameter($mimetypeId)));
+
+		$mimetype = $qb->execute()->fetch();
+		$this->assertEquals('testing/mymimetype', $mimetype['mimetype']);
+
+		$this->assertEquals('testing/mymimetype', $this->loader->getMimetypeById($mimetypeId));
+		$this->assertEquals($mimetypeId, $this->loader->getId('testing/mymimetype'));
+	}
+
+	public function testStoreExists() {
+		$mimetypeId = $this->loader->getId('testing/mymimetype');
+		$mimetypeId2 = $this->loader->getId('testing/mymimetype');
+
+		$this->assertEquals($mimetypeId, $mimetypeId2);
+	}
+
+}
diff --git a/tests/lib/repair/repairmimetypes.php b/tests/lib/repair/repairmimetypes.php
index 40ffc14612bc32c8143238a121848e089897394e..76d4d7cc656beea7ddf03314e4ce0746f76e99ef 100644
--- a/tests/lib/repair/repairmimetypes.php
+++ b/tests/lib/repair/repairmimetypes.php
@@ -22,8 +22,17 @@ class RepairMimeTypes extends \Test\TestCase {
 
 	protected function setUp() {
 		parent::setUp();
-		$this->storage = new \OC\Files\Storage\Temporary([]);
 
+		$this->savedMimetypeLoader = \OC::$server->getMimeTypeLoader();
+		$this->mimetypeLoader = $this->getMockBuilder('\OC\Files\Type\Loader')
+			->setConstructorArgs([\OC::$server->getDatabaseConnection()])
+			->setMethods(null)
+			->getMock();
+		\OC::$server->registerService('MimeTypeLoader', function ($c) {
+			return $this->mimetypeLoader;
+		});
+
+		$this->storage = new \OC\Files\Storage\Temporary([]);
 		$this->repair = new \OC\Repair\RepairMimeTypes();
 	}
 
@@ -33,7 +42,9 @@ class RepairMimeTypes extends \Test\TestCase {
 		\OC_DB::executeAudited($sql, [$this->storage->getId()]);
 		$this->clearMimeTypes();
 
-		DummyFileCache::clearCachedMimeTypes();
+		\OC::$server->registerService('MimeTypeLoader', function($c) {
+			return $this->savedMimetypeLoader;
+		});
 
 		parent::tearDown();
 	}
@@ -86,8 +97,7 @@ class RepairMimeTypes extends \Test\TestCase {
 		$this->repair->run();
 
 		// force mimetype reload
-		DummyFileCache::clearCachedMimeTypes();
-		$this->storage->getCache()->loadMimeTypes();
+		self::invokePrivate($this->mimetypeLoader, 'loadMimetypes');
 
 		$this->checkEntries($fixedMimeTypes);
 	}
@@ -434,14 +444,3 @@ class RepairMimeTypes extends \Test\TestCase {
 	}
 }
 
-/**
- * Dummy class to access protected members
- */
-class DummyFileCache extends \OC\Files\Cache\Cache {
-
-	public static function clearCachedMimeTypes() {
-		self::$mimetypeIds = [];
-		self::$mimetypes = [];
-	}
-}
-