diff --git a/typo3/sysext/backend/Classes/Form/Element/UserSysFileStorageIsPublicElement.php b/typo3/sysext/backend/Classes/Form/Element/UserSysFileStorageIsPublicElement.php
index 620b1c4d313e6adc671782951b95ff92c6bb4370..203254d8f2173fd643c7c677837d48631c7ed727 100644
--- a/typo3/sysext/backend/Classes/Form/Element/UserSysFileStorageIsPublicElement.php
+++ b/typo3/sysext/backend/Classes/Form/Element/UserSysFileStorageIsPublicElement.php
@@ -21,7 +21,7 @@ use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageService;
 use TYPO3\CMS\Core\Resource\Exception\InvalidPathException;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -61,7 +61,7 @@ class UserSysFileStorageIsPublicElement extends AbstractFormElement
             $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
             $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
             try {
-                $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject((int)$row['uid']);
+                $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$row['uid']);
                 $storageRecord = $storage->getStorageRecord();
                 $isPublic = $storage->isPublic() && $storageRecord['is_public'];
 
diff --git a/typo3/sysext/core/Classes/Resource/File.php b/typo3/sysext/core/Classes/Resource/File.php
index e4607c041ca4d86c9cdc21af1b19f7085f16f7c6..1863dd28ad4e53fabbf48d6bd7fb9f6403b6c58c 100644
--- a/typo3/sysext/core/Classes/Resource/File.php
+++ b/typo3/sysext/core/Classes/Resource/File.php
@@ -195,7 +195,7 @@ class File extends AbstractFile
             $this->getType();
         }
         if (array_key_exists('storage', $properties) && in_array('storage', $this->updatedProperties)) {
-            $this->storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($properties['storage']);
+            $this->storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$properties['storage']);
         }
     }
 
diff --git a/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php b/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
index fa3a17d1cb17a1a020cd7c1c4b725117c31fc82a..afe14c8dcd03241703342de69973b8dfa5202fe1 100644
--- a/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
+++ b/typo3/sysext/core/Classes/Resource/Index/FileIndexRepository.php
@@ -26,7 +26,6 @@ use TYPO3\CMS\Core\Resource\Event\AfterFileUpdatedInIndexEvent;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\Folder;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -61,16 +60,6 @@ class FileIndexRepository implements SingletonInterface
         'mime_type', 'name', 'sha1', 'size', 'creation_date', 'modification_date', 'folder_hash'
     ];
 
-    /**
-     * Gets the Resource Factory
-     *
-     * @return ResourceFactory
-     */
-    protected function getResourceFactory()
-    {
-        return GeneralUtility::makeInstance(ResourceFactory::class);
-    }
-
     /**
      * Returns an Instance of the Repository
      *
@@ -86,18 +75,6 @@ class FileIndexRepository implements SingletonInterface
         $this->eventDispatcher = $eventDispatcher;
     }
 
-    /**
-     * Retrieves Index record for a given $combinedIdentifier
-     *
-     * @param string $combinedIdentifier
-     * @return array|bool
-     */
-    public function findOneByCombinedIdentifier($combinedIdentifier)
-    {
-        [$storageUid, $identifier] = GeneralUtility::trimExplode(':', $combinedIdentifier, false, 2);
-        return $this->findOneByStorageUidAndIdentifier($storageUid, $identifier);
-    }
-
     /**
      * Retrieves Index record for a given $fileUid
      *
@@ -121,21 +98,6 @@ class FileIndexRepository implements SingletonInterface
         return is_array($row) ? $row : false;
     }
 
-    /**
-     * Retrieves Index record for a given $storageUid and $identifier
-     *
-     * @param int $storageUid
-     * @param string $identifier
-     * @return array|bool
-     *
-     * @internal only for use from FileRepository
-     */
-    public function findOneByStorageUidAndIdentifier($storageUid, $identifier)
-    {
-        $identifierHash = $this->getResourceFactory()->getStorageObject($storageUid)->hashFileIdentifier($identifier);
-        return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
-    }
-
     /**
      * Retrieves Index record for a given $storageUid and $identifier
      *
@@ -163,6 +125,21 @@ class FileIndexRepository implements SingletonInterface
         return is_array($row) ? $row : false;
     }
 
+    /**
+     * Retrieves Index record for a given $storageUid and $identifier
+     *
+     * @param ResourceStorage $storage
+     * @param string $identifier
+     * @return array|bool
+     *
+     * @internal only for use from FileRepository
+     */
+    public function findOneByStorageAndIdentifier(ResourceStorage $storage, $identifier)
+    {
+        $identifierHash = $storage->hashFileIdentifier($identifier);
+        return $this->findOneByStorageUidAndIdentifierHash($storage->getUid(), $identifierHash);
+    }
+
     /**
      * Retrieves Index record for a given $fileObject
      *
@@ -173,9 +150,7 @@ class FileIndexRepository implements SingletonInterface
      */
     public function findOneByFileObject(FileInterface $fileObject)
     {
-        $storageUid = $fileObject->getStorage()->getUid();
-        $identifierHash = $fileObject->getHashedIdentifier();
-        return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
+        return $this->findOneByStorageAndIdentifier($fileObject->getStorage(), $fileObject->getIdentifier());
     }
 
     /**
diff --git a/typo3/sysext/core/Classes/Resource/Index/Indexer.php b/typo3/sysext/core/Classes/Resource/Index/Indexer.php
index c9a156fa2b20b1decdc2a3fd21c9b5cdb09f341e..c72d91d7a3ac590757678979a004e02e1649188f 100644
--- a/typo3/sysext/core/Classes/Resource/Index/Indexer.php
+++ b/typo3/sysext/core/Classes/Resource/Index/Indexer.php
@@ -213,7 +213,7 @@ class Indexer implements LoggerAwareInterface
             // Get the modification time for file-identifier from the storage
             $modificationTime = $this->storage->getFileInfoByIdentifier($fileIdentifier, ['mtime']);
             // Look if the the modification time in FS is higher than the one in database (key needed on timestamps)
-            $indexRecord = $this->getFileIndexRepository()->findOneByStorageUidAndIdentifier($this->storage->getUid(), $fileIdentifier);
+            $indexRecord = $this->getFileIndexRepository()->findOneByStorageAndIdentifier($this->storage, $fileIdentifier);
 
             if ($indexRecord !== false) {
                 $this->identifiedFileUids[] = $indexRecord['uid'];
diff --git a/typo3/sysext/core/Classes/Resource/ProcessedFile.php b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
index db2990e81926ce276b7370d61636aaf2c2c24160..48563f109b32e9caa26843e9a10837367d41f475 100644
--- a/typo3/sysext/core/Classes/Resource/ProcessedFile.php
+++ b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
@@ -143,7 +143,7 @@ class ProcessedFile extends AbstractFile
         $this->properties = $databaseRow;
 
         if (!empty($databaseRow['storage']) && (int)$this->storage->getUid() !== (int)$databaseRow['storage']) {
-            $this->storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($databaseRow['storage']);
+            $this->storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid($databaseRow['storage']);
         }
     }
 
diff --git a/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php b/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
index 7a3c2f31d08a427e0417047c3f7d8d47c89803fc..8f1e2cf6fe2c57f913c3ac5d33400ef837d841bb 100644
--- a/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
+++ b/typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
@@ -88,7 +88,6 @@ class ProcessedFileRepository extends AbstractRepository implements LoggerAwareI
     protected function createDomainObject(array $databaseRow)
     {
         $originalFile = $this->factory->getFileObject((int)$databaseRow['original']);
-        $originalFile->setStorage($this->factory->getStorageObject($originalFile->getProperty('storage')));
         $taskType = $databaseRow['task_type'];
         // Allow deserialization of Area class, since Area objects get serialized in configuration
         // TODO: This should be changed to json encode and decode at some point
diff --git a/typo3/sysext/core/Classes/Resource/ResourceFactory.php b/typo3/sysext/core/Classes/Resource/ResourceFactory.php
index 926de99a915a79c2f46c663edd96b960d2076b19..9e8b325a3fcf63b916263842ecfd75952b1564cd 100644
--- a/typo3/sysext/core/Classes/Resource/ResourceFactory.php
+++ b/typo3/sysext/core/Classes/Resource/ResourceFactory.php
@@ -15,19 +15,15 @@
 
 namespace TYPO3\CMS\Core\Resource;
 
-use Psr\EventDispatcher\EventDispatcherInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Collection\CollectionInterface;
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Resource\Collection\FileCollectionRegistry;
-use TYPO3\CMS\Core\Resource\Driver\DriverRegistry;
-use TYPO3\CMS\Core\Resource\Event\AfterResourceStorageInitializationEvent;
-use TYPO3\CMS\Core\Resource\Event\BeforeResourceStorageInitializationEvent;
 use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
 use TYPO3\CMS\Core\Resource\Index\FileIndexRepository;
-use TYPO3\CMS\Core\Resource\Index\Indexer;
 use TYPO3\CMS\Core\Service\FlexFormService;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -39,11 +35,6 @@ use TYPO3\CMS\Core\Utility\PathUtility;
  */
 class ResourceFactory implements SingletonInterface
 {
-    /**
-     * @var ResourceStorage[]
-     */
-    protected $storageInstances = [];
-
     /**
      * @var Collection\AbstractFileCollection[]
      */
@@ -60,40 +51,13 @@ class ResourceFactory implements SingletonInterface
     protected $fileReferenceInstances = [];
 
     /**
-     * A list of the base paths of "local" driver storages. Used to make the detection of base paths easier.
-     *
-     * @var array
-     */
-    protected $localDriverStorageCache;
-
-    /**
-     * @var EventDispatcherInterface
-     */
-    protected $eventDispatcher;
-
-    /**
-     * @param EventDispatcherInterface $eventDispatcher
+     * @var StorageRepository
      */
-    public function __construct(EventDispatcherInterface $eventDispatcher)
-    {
-        $this->eventDispatcher = $eventDispatcher;
-    }
+    protected $storageRepository;
 
-    /**
-     * Creates a driver object for a specified storage object.
-     *
-     * @param string $driverIdentificationString The driver class (or identifier) to use.
-     * @param array $driverConfiguration The configuration of the storage
-     * @return Driver\DriverInterface
-     * @throws \InvalidArgumentException
-     */
-    public function getDriverObject($driverIdentificationString, array $driverConfiguration)
+    public function __construct(StorageRepository $storageRepository)
     {
-        /** @var Driver\DriverRegistry $driverRegistry */
-        $driverRegistry = GeneralUtility::makeInstance(DriverRegistry::class);
-        $driverClass = $driverRegistry->getDriverClass($driverIdentificationString);
-        $driverObject = GeneralUtility::makeInstance($driverClass, $driverConfiguration);
-        return $driverObject;
+        $this->storageRepository = $storageRepository;
     }
 
     /**
@@ -105,20 +69,13 @@ class ResourceFactory implements SingletonInterface
      * TYPO3 installation.
      *
      * @return ResourceStorage|null
+     * @internal It is recommended to use the StorageRepository in the future, and this is only kept as backwards-compat layer
      */
     public function getDefaultStorage()
     {
-        /** @var StorageRepository $storageRepository */
-        $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
-
-        $allStorages = $storageRepository->findAll();
-        foreach ($allStorages as $storage) {
-            if ($storage->isDefault()) {
-                return $storage;
-            }
-        }
-        return null;
+        return $this->storageRepository->getDefaultStorage();
     }
+
     /**
      * Creates an instance of the storage from given UID. The $recordData can
      * be supplied to increase performance.
@@ -129,114 +86,22 @@ class ResourceFactory implements SingletonInterface
      *
      * @throws \InvalidArgumentException
      * @return ResourceStorage
+     * @internal It is recommended to use the StorageRepository in the future, and this is only kept as backwards-compat layer
      */
     public function getStorageObject($uid, array $recordData = [], &$fileIdentifier = null)
     {
-        if (!is_numeric($uid)) {
-            throw new \InvalidArgumentException('The UID of storage has to be numeric. UID given: "' . $uid . '"', 1314085991);
-        }
-        $uid = (int)$uid;
-        if ($uid === 0 && $fileIdentifier !== null) {
-            $uid = $this->findBestMatchingStorageByLocalPath($fileIdentifier);
-        }
-        if (empty($this->storageInstances[$uid])) {
-            $storageConfiguration = null;
-            /** @var BeforeResourceStorageInitializationEvent $event */
-            $event = $this->eventDispatcher->dispatch(new BeforeResourceStorageInitializationEvent($uid, $recordData, $fileIdentifier));
-            $recordData = $event->getRecord();
-            $uid = $event->getStorageUid();
-            $fileIdentifier = $event->getFileIdentifier();
-            // If the built-in storage with UID=0 is requested:
-            if ($uid === 0) {
-                $recordData = [
-                    'uid' => 0,
-                    'pid' => 0,
-                    'name' => 'Fallback Storage',
-                    'description' => 'Internal storage, mounting the main TYPO3_site directory.',
-                    'driver' => 'Local',
-                    'processingfolder' => 'typo3temp/assets/_processed_/',
-                    // legacy code
-                    'configuration' => '',
-                    'is_online' => true,
-                    'is_browsable' => true,
-                    'is_public' => true,
-                    'is_writable' => true,
-                    'is_default' => false,
-                ];
-                $storageConfiguration = [
-                    'basePath' => '/',
-                    'pathType' => 'relative'
-                ];
-            } elseif ($recordData === [] || (int)$recordData['uid'] !== $uid) {
-                /** @var StorageRepository $storageRepository */
-                $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
-                $recordData = $storageRepository->fetchRowByUid($uid);
-            }
-            $storageObject = $this->createStorageObject($recordData, $storageConfiguration);
-            $storageObject = $this->eventDispatcher
-                ->dispatch(new AfterResourceStorageInitializationEvent($storageObject))
-                ->getStorage();
-            $this->storageInstances[$uid] = $storageObject;
-        }
-        return $this->storageInstances[$uid];
+        return $this->storageRepository->getStorageObject($uid, $recordData, $fileIdentifier);
     }
 
     /**
-     * Checks whether a file resides within a real storage in local file system.
-     * If no match is found, uid 0 is returned which is a fallback storage pointing to fileadmin in public web path.
-     *
-     * The file identifier is adapted accordingly to match the new storage's base path.
+     * Converts a flexform data string to a flat array with key value pairs.
      *
-     * @param string $localPath
-     *
-     * @return int
-     */
-    protected function findBestMatchingStorageByLocalPath(&$localPath)
-    {
-        if ($this->localDriverStorageCache === null) {
-            $this->initializeLocalStorageCache();
-        }
-
-        $bestMatchStorageUid = 0;
-        $bestMatchLength = 0;
-        foreach ($this->localDriverStorageCache as $storageUid => $basePath) {
-            $matchLength = strlen(PathUtility::getCommonPrefix([$basePath, $localPath]));
-            $basePathLength = strlen($basePath);
-
-            if ($matchLength >= $basePathLength && $matchLength > $bestMatchLength) {
-                $bestMatchStorageUid = (int)$storageUid;
-                $bestMatchLength = $matchLength;
-            }
-        }
-        if ($bestMatchStorageUid !== 0) {
-            $localPath = substr($localPath, $bestMatchLength);
-        }
-        return $bestMatchStorageUid;
-    }
-
-    /**
-     * Creates an array mapping all uids to the basePath of storages using the "local" driver.
-     */
-    protected function initializeLocalStorageCache()
-    {
-        /** @var StorageRepository $storageRepository */
-        $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
-        /** @var ResourceStorage[] $storageObjects */
-        $storageObjects = $storageRepository->findByStorageType('Local');
-
-        $storageCache = [];
-        foreach ($storageObjects as $localStorage) {
-            $configuration = $localStorage->getConfiguration();
-            $storageCache[$localStorage->getUid()] = $configuration['basePath'];
-        }
-        $this->localDriverStorageCache = $storageCache;
-    }
-
-    /**
-     * Converts a flexform data string to a flat array with key value pairs
+     * It is recommended to not use this functionality directly, and instead implement this code yourself, as this
+     * code has nothing to do with a Public API for Resources.
      *
      * @param string $flexFormData
      * @return array Array with key => value pairs of the field data in the FlexForm
+     * @internal
      */
     public function convertFlexFormDataToConfigurationArray($flexFormData)
     {
@@ -291,7 +156,7 @@ class ResourceFactory implements SingletonInterface
      * Creates a collection object.
      *
      * @param array $collectionData The database row of the sys_file_collection record.
-     * @return Collection\AbstractFileCollection
+     * @return Collection\AbstractFileCollection|CollectionInterface
      */
     public function createCollectionObject(array $collectionData)
     {
@@ -308,17 +173,13 @@ class ResourceFactory implements SingletonInterface
      * Creates a storage object from a storage database row.
      *
      * @param array $storageRecord
-     * @param array $storageConfiguration Storage configuration (if given, this won't be extracted from the FlexForm value but the supplied array used instead)
+     * @param array|null $storageConfiguration Storage configuration (if given, this won't be extracted from the FlexForm value but the supplied array used instead)
      * @return ResourceStorage
+     * @internal It is recommended to use the StorageRepository in the future, and this is only kept as backwards-compat layer
      */
     public function createStorageObject(array $storageRecord, array $storageConfiguration = null)
     {
-        if (!$storageConfiguration) {
-            $storageConfiguration = $this->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
-        }
-        $driverType = $storageRecord['driver'];
-        $driverObject = $this->getDriverObject($driverType, $storageConfiguration);
-        return GeneralUtility::makeInstance(ResourceStorage::class, $driverObject, $storageRecord, $this->eventDispatcher);
+        return $this->storageRepository->createStorageObject($storageRecord, $storageConfiguration);
     }
 
     /**
@@ -328,6 +189,7 @@ class ResourceFactory implements SingletonInterface
      * @param string $identifier The path to the folder. Might also be a simple unique string, depending on the storage driver.
      * @param string $name The name of the folder (e.g. the folder name)
      * @return Folder
+     * @internal it is recommended to access the ResourceStorage object directly and access ->getFolder($identifier) this method is kept for backwards compatibility
      */
     public function createFolderObject(ResourceStorage $storage, $identifier, $name)
     {
@@ -385,10 +247,8 @@ class ResourceFactory implements SingletonInterface
             $storageUid = 0;
             $fileIdentifier = $parts[0];
         }
-
-        // please note that getStorageObject() might modify $fileIdentifier when
-        // auto-detecting the best-matching storage to use
-        return $this->getFileObjectByStorageAndIdentifier($storageUid, $fileIdentifier);
+        return $this->storageRepository->getStorageObject($storageUid, [], $fileIdentifier)
+            ->getFileByIdentifier($fileIdentifier);
     }
 
     /**
@@ -396,25 +256,17 @@ class ResourceFactory implements SingletonInterface
      * If the file is outside of the process folder, it gets indexed and returned as file object afterwards
      * If the file is within processing folder, the file object will be directly returned
      *
-     * @param int $storageUid
+     * @param ResourceStorage|int $storage
      * @param string $fileIdentifier
      * @return File|ProcessedFile|null
+     * @internal It is recommended to use the StorageRepository in the future, and this is only kept as backwards-compat layer
      */
-    public function getFileObjectByStorageAndIdentifier($storageUid, &$fileIdentifier)
+    public function getFileObjectByStorageAndIdentifier($storage, &$fileIdentifier)
     {
-        $storage = $this->getStorageObject($storageUid, [], $fileIdentifier);
-        if (!$storage->isWithinProcessingFolder($fileIdentifier)) {
-            $fileData = $this->getFileIndexRepository()->findOneByStorageUidAndIdentifier($storage->getUid(), $fileIdentifier);
-            if ($fileData === false) {
-                $fileObject = $this->getIndexer($storage)->createIndexEntry($fileIdentifier);
-            } else {
-                $fileObject = $this->getFileObject($fileData['uid'], $fileData);
-            }
-        } else {
-            $fileObject = $this->getProcessedFileRepository()->findByStorageAndIdentifier($storage, $fileIdentifier);
+        if (!($storage instanceof ResourceStorage)) {
+            $storage = $this->storageRepository->getStorageObject($storage, [], $fileIdentifier);
         }
-
-        return $fileObject;
+        return $storage->getFileByIdentifier($fileIdentifier);
     }
 
     /**
@@ -504,7 +356,7 @@ class ResourceFactory implements SingletonInterface
                 $folderIdentifier = PathUtility::stripPathSitePrefix($parts[0]);
             }
         }
-        return $this->getStorageObject($storageUid, [], $folderIdentifier)->getFolder($folderIdentifier);
+        return $this->storageRepository->getStorageObject($storageUid, [], $folderIdentifier)->getFolder($folderIdentifier);
     }
 
     /**
@@ -512,12 +364,13 @@ class ResourceFactory implements SingletonInterface
      *
      * @param string $identifier An identifier of the form [storage uid]:[object identifier]
      * @return ResourceStorage
+     * @internal It is recommended to use the StorageRepository in the future, and this is only kept as backwards-compat layer
      */
     public function getStorageObjectFromCombinedIdentifier($identifier)
     {
         $parts = GeneralUtility::trimExplode(':', $identifier);
         $storageUid = count($parts) === 2 ? $parts[0] : null;
-        return $this->getStorageObject($storageUid);
+        return $this->storageRepository->findByUid($storageUid);
     }
 
     /**
@@ -531,7 +384,7 @@ class ResourceFactory implements SingletonInterface
     public function getObjectFromCombinedIdentifier($identifier)
     {
         [$storageId, $objectIdentifier] = GeneralUtility::trimExplode(':', $identifier);
-        $storage = $this->getStorageObject($storageId);
+        $storage = $this->storageRepository->findByUid($storageId);
         if ($storage->hasFile($objectIdentifier)) {
             return $storage->getFile($objectIdentifier);
         }
@@ -552,7 +405,7 @@ class ResourceFactory implements SingletonInterface
     public function createFileObject(array $fileData, ResourceStorage $storage = null)
     {
         if (array_key_exists('storage', $fileData) && MathUtility::canBeInterpretedAsInteger($fileData['storage'])) {
-            $storageObject = $this->getStorageObject((int)$fileData['storage']);
+            $storageObject = $this->storageRepository->findByUid((int)$fileData['storage']);
         } elseif ($storage !== null) {
             $storageObject = $storage;
             $fileData['storage'] = $storage->getUid();
@@ -653,25 +506,4 @@ class ResourceFactory implements SingletonInterface
     {
         return FileIndexRepository::getInstance();
     }
-
-    /**
-     * Returns an instance of the ProcessedFileRepository
-     *
-     * @return ProcessedFileRepository
-     */
-    protected function getProcessedFileRepository()
-    {
-        return GeneralUtility::makeInstance(ProcessedFileRepository::class);
-    }
-
-    /**
-     * Returns an instance of the Indexer
-     *
-     * @param ResourceStorage $storage
-     * @return Index\Indexer
-     */
-    protected function getIndexer(ResourceStorage $storage)
-    {
-        return GeneralUtility::makeInstance(Indexer::class, $storage);
-    }
 }
diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
index 5edbefa2e45c751aef8d60027343e89779cbc7ce..d1667f59478627994289442de88ff5835471ad39 100644
--- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php
+++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
@@ -80,6 +80,7 @@ use TYPO3\CMS\Core\Resource\Search\Result\FileSearchResult;
 use TYPO3\CMS\Core\Resource\Search\Result\FileSearchResultInterface;
 use TYPO3\CMS\Core\Resource\Security\FileNameValidator;
 use TYPO3\CMS\Core\Resource\Service\FileProcessingService;
+use TYPO3\CMS\Core\Service\FlexFormService;
 use TYPO3\CMS\Core\Utility\Exception\NotImplementedMethodException;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
@@ -230,7 +231,13 @@ class ResourceStorage implements ResourceStorageInterface
     {
         $this->storageRecord = $storageRecord;
         $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::getContainer()->get(EventDispatcherInterface::class);
-        $this->configuration = $this->getResourceFactoryInstance()->convertFlexFormDataToConfigurationArray($storageRecord['configuration'] ?? '');
+        if (is_array($storageRecord['configuration'] ?? null)) {
+            $this->configuration = $storageRecord['configuration'];
+        } elseif (!empty($storageRecord['configuration'] ?? '')) {
+            $this->configuration = GeneralUtility::makeInstance(FlexFormService::class)->convertFlexFormContentToArray($storageRecord['configuration']);
+        } else {
+            $this->configuration = [];
+        }
         $this->capabilities =
             ($this->storageRecord['is_browsable'] ?? null ? self::CAPABILITY_BROWSABLE : 0) |
             ($this->storageRecord['is_public'] ?? null ? self::CAPABILITY_PUBLIC : 0) |
@@ -555,7 +562,7 @@ class ResourceStorage implements ResourceStorageInterface
             throw new FolderDoesNotExistException('Folder for file mount ' . $folderIdentifier . ' does not exist.', 1334427099);
         }
         $data = $this->driver->getFolderInfoByIdentifier($folderIdentifier);
-        $folderObject = $this->getResourceFactoryInstance()->createFolderObject($this, $data['identifier'], $data['name']);
+        $folderObject = $this->createFolderObject($data['identifier'], $data['name']);
         // Use the canonical identifier instead of the user provided one!
         $folderIdentifier = $folderObject->getIdentifier();
         if (
@@ -1260,7 +1267,7 @@ class ResourceStorage implements ResourceStorageInterface
         }
 
         $fileIdentifier = $this->driver->addFile($localFilePath, $targetFolder->getIdentifier(), $targetFileName, $removeOriginal);
-        $file = $this->getResourceFactoryInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $fileIdentifier);
+        $file = $this->getFileByIdentifier($fileIdentifier);
 
         if ($replaceExisting && $file instanceof File) {
             $this->getIndexer()->updateIndexEntry($file);
@@ -1443,13 +1450,38 @@ class ResourceStorage implements ResourceStorageInterface
      */
     public function getFile($identifier)
     {
-        $file = $this->getFileFactory()->getFileObjectByStorageAndIdentifier($this->getUid(), $identifier);
+        $file = $this->getFileByIdentifier($identifier);
         if (!$this->driver->fileExists($identifier)) {
             $file->setMissing(true);
         }
         return $file;
     }
 
+    /**
+     * Gets a file object from storage by file identifier
+     * If the file is outside of the process folder, it gets indexed and returned as file object afterwards
+     * If the file is within processing folder, the file object will be directly returned
+     *
+     * @param string $fileIdentifier
+     * @return File|ProcessedFile|null
+     */
+    public function getFileByIdentifier(string $fileIdentifier)
+    {
+        if (!$this->isWithinProcessingFolder($fileIdentifier)) {
+            $fileData = $this->getFileIndexRepository()->findOneByStorageAndIdentifier($this, $fileIdentifier);
+            if ($fileData === false) {
+                return $this->getIndexer()->createIndexEntry($fileIdentifier);
+            }
+            return $this->getResourceFactoryInstance()->getFileObject($fileData['uid'], $fileData);
+        }
+        return $this->getProcessedFileRepository()->findByStorageAndIdentifier($this, $fileIdentifier);
+    }
+
+    protected function getProcessedFileRepository(): ProcessedFileRepository
+    {
+        return GeneralUtility::makeInstance(ProcessedFileRepository::class);
+    }
+
     /**
      * Gets information about a file.
      *
@@ -1539,7 +1571,7 @@ class ResourceStorage implements ResourceStorageInterface
     public function getFileInFolder($fileName, Folder $folder)
     {
         $identifier = $this->driver->getFileInFolder($fileName, $folder->getIdentifier());
-        return $this->getFileFactory()->getFileObjectByStorageAndIdentifier($this->getUid(), $identifier);
+        return $this->getFileByIdentifier($identifier);
     }
 
     /**
@@ -1571,7 +1603,7 @@ class ResourceStorage implements ResourceStorageInterface
             if (isset($rows[$identifier])) {
                 $fileObject = $this->getFileFactory()->getFileObject($rows[$identifier]['uid'], $rows[$identifier]);
             } else {
-                $fileObject = $this->getFileFactory()->getFileObjectByStorageAndIdentifier($this->getUid(), $identifier);
+                $fileObject = $this->getFileByIdentifier($identifier);
             }
             if ($fileObject instanceof FileInterface) {
                 $key = $fileObject->getName();
@@ -1658,7 +1690,7 @@ class ResourceStorage implements ResourceStorageInterface
                 if (empty($processingFolderIdentifier) || (int)$storageUid !== $this->getUid()) {
                     continue;
                 }
-                $potentialProcessingFolder = $this->getResourceFactoryInstance()->createFolderObject($this, $processingFolderIdentifier, $processingFolderIdentifier);
+                $potentialProcessingFolder = $this->createFolderObject($processingFolderIdentifier, $processingFolderIdentifier);
                 if ($potentialProcessingFolder->getStorage() === $this && $potentialProcessingFolder->getIdentifier() !== $this->getProcessingFolder()->getIdentifier()) {
                     $this->processingFolders[] = $potentialProcessingFolder;
                 }
@@ -1824,7 +1856,7 @@ class ResourceStorage implements ResourceStorageInterface
         $this->eventDispatcher->dispatch(
             new AfterFileCreatedEvent($newFileIdentifier, $targetFolderObject)
         );
-        return $this->getResourceFactoryInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $newFileIdentifier);
+        return $this->getFileByIdentifier($newFileIdentifier);
     }
 
     /**
@@ -1919,7 +1951,7 @@ class ResourceStorage implements ResourceStorageInterface
             $tempPath = $file->getForLocalProcessing();
             $newFileObjectIdentifier = $this->driver->addFile($tempPath, $targetFolder->getIdentifier(), $sanitizedTargetFileName);
         }
-        $newFileObject = $this->getResourceFactoryInstance()->getFileObjectByStorageAndIdentifier($this->getUid(), $newFileObjectIdentifier);
+        $newFileObject = $this->getFileByIdentifier($newFileObjectIdentifier);
 
         $this->eventDispatcher->dispatch(
             new AfterFileCopiedEvent($file, $targetFolder, $newFileObjectIdentifier, $newFileObject)
@@ -2508,7 +2540,7 @@ class ResourceStorage implements ResourceStorageInterface
     public function getFolder($identifier, $returnInaccessibleFolderObject = false)
     {
         $data = $this->driver->getFolderInfoByIdentifier($identifier);
-        $folder = $this->getResourceFactoryInstance()->createFolderObject($this, $data['identifier'] ?? null, $data['name'] ?? null);
+        $folder = $this->createFolderObject($data['identifier'] ?? '', $data['name'] ?? '');
 
         try {
             $this->assureFolderReadPermission($folder);
@@ -2585,7 +2617,7 @@ class ResourceStorage implements ResourceStorageInterface
             $mount = reset($this->fileMounts);
             return $mount['folder'];
         }
-        return $this->getResourceFactoryInstance()->createFolderObject($this, $this->driver->getRootLevelFolder(), '');
+        return $this->createFolderObject($this->driver->getRootLevelFolder(), '');
     }
 
     /**
@@ -2716,7 +2748,7 @@ class ResourceStorage implements ResourceStorageInterface
             try {
                 if (strpos($processingFolder, ':') !== false) {
                     [$storageUid, $processingFolderIdentifier] = explode(':', $processingFolder, 2);
-                    $storage = $this->getResourceFactoryInstance()->getStorageObject($storageUid);
+                    $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$storageUid);
                     if ($storage->hasFolder($processingFolderIdentifier)) {
                         $this->processingFolder = $storage->getFolder($processingFolderIdentifier);
                     } else {
@@ -2750,7 +2782,7 @@ class ResourceStorage implements ResourceStorageInterface
                         }
                     } else {
                         $data = $this->driver->getFolderInfoByIdentifier($processingFolder);
-                        $this->processingFolder = $this->getResourceFactoryInstance()->createFolderObject($this, $data['identifier'], $data['name']);
+                        $this->processingFolder = $this->createFolderObject($data['identifier'], $data['name']);
                     }
                 }
             } catch (InsufficientFolderWritePermissionsException|ResourcePermissionsUnavailableException $e) {
@@ -2921,4 +2953,16 @@ class ResourceStorage implements ResourceStorageInterface
 
         return $recyclerFolder;
     }
+
+    /**
+     * Creates a folder to directly access (a part of) a storage.
+     *
+     * @param string $identifier The path to the folder. Might also be a simple unique string, depending on the storage driver.
+     * @param string $name The name of the folder (e.g. the folder name)
+     * @return Folder
+     */
+    protected function createFolderObject(string $identifier, string $name)
+    {
+        return GeneralUtility::makeInstance(Folder::class, $this, $identifier, $name);
+    }
 }
diff --git a/typo3/sysext/core/Classes/Resource/StorageRepository.php b/typo3/sysext/core/Classes/Resource/StorageRepository.php
index 78d4ffa78ca713856d45ce4f261b7171256e8b09..aa20cabc26b4e57a52140b51ee09ea65fac7d571 100644
--- a/typo3/sysext/core/Classes/Resource/StorageRepository.php
+++ b/typo3/sysext/core/Classes/Resource/StorageRepository.php
@@ -1,5 +1,7 @@
 <?php
 
+declare(strict_types=1);
+
 /*
  * This file is part of the TYPO3 CMS project.
  *
@@ -15,19 +17,24 @@
 
 namespace TYPO3\CMS\Core\Resource;
 
+use Psr\EventDispatcher\EventDispatcherInterface;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
+use TYPO3\CMS\Core\Resource\Driver\DriverInterface;
 use TYPO3\CMS\Core\Resource\Driver\DriverRegistry;
+use TYPO3\CMS\Core\Resource\Event\AfterResourceStorageInitializationEvent;
+use TYPO3\CMS\Core\Resource\Event\BeforeResourceStorageInitializationEvent;
+use TYPO3\CMS\Core\Service\FlexFormService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 
 /**
- * Repository for accessing the file mounts
+ * Repository for accessing the file storages
  */
-class StorageRepository extends AbstractRepository implements LoggerAwareInterface
+class StorageRepository implements LoggerAwareInterface
 {
     use LoggerAwareTrait;
 
@@ -37,9 +44,9 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
     protected $storageRowCache;
 
     /**
-     * @var string
+     * @var array|null
      */
-    protected $objectType = ResourceStorage::class;
+    protected $localDriverStorageCache;
 
     /**
      * @var string
@@ -47,38 +54,73 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
     protected $table = 'sys_file_storage';
 
     /**
-     * @var string
+     * @var DriverRegistry
      */
-    protected $typeField = 'driver';
+    protected $driverRegistry;
 
     /**
-     * @var string
+     * @var EventDispatcherInterface
      */
-    protected $driverField = 'driver';
+    protected $eventDispatcher;
 
     /**
-     * @param int $uid
+     * @var ResourceStorage[]
+     */
+    protected $storageInstances;
+
+    public function __construct(EventDispatcherInterface $eventDispatcher, DriverRegistry $driverRegistry)
+    {
+        $this->eventDispatcher = $eventDispatcher;
+        $this->driverRegistry = $driverRegistry;
+    }
+
+    /**
+     * Returns the Default Storage
+     *
+     * The Default Storage is considered to be the replacement for the fileadmin/ construct.
+     * It is automatically created with the setting fileadminDir from install tool.
+     * getDefaultStorage->getDefaultFolder() will get you fileadmin/user_upload/ in a standard
+     * TYPO3 installation.
      *
      * @return ResourceStorage|null
      */
-    public function findByUid($uid)
+    public function getDefaultStorage(): ?ResourceStorage
+    {
+        $allStorages = $this->findAll();
+        foreach ($allStorages as $storage) {
+            if ($storage->isDefault()) {
+                return $storage;
+            }
+        }
+        return null;
+    }
+
+    public function findByUid(int $uid): ?ResourceStorage
     {
         $this->initializeLocalCache();
-        if (isset($this->storageRowCache[$uid])) {
-            return $this->factory->getStorageObject($uid, $this->storageRowCache[$uid]);
+        if (isset($this->storageRowCache[$uid]) || $uid === 0) {
+            return $this->getStorageObject($uid, $this->storageRowCache[$uid] ?? []);
         }
         return null;
     }
 
     /**
-     * Only for use in ResourceFactory::getStorageObject
+     * Gets a storage object from a combined identifier
      *
-     * @internal
+     * @param string $identifier An identifier of the form [storage uid]:[object identifier]
+     * @return ResourceStorage|null
+     */
+    public function findByCombinedIdentifier(string $identifier): ?ResourceStorage
+    {
+        $parts = GeneralUtility::trimExplode(':', $identifier);
+        return count($parts) === 2 ? $this->findByUid((int)$parts[0]) : null;
+    }
+
+    /**
      * @param int $uid
-     *
      * @return array
      */
-    public function fetchRowByUid(int $uid): array
+    protected function fetchRecordDataByUid(int $uid): array
     {
         $this->initializeLocalCache();
         if (!isset($this->storageRowCache[$uid])) {
@@ -97,10 +139,6 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
             $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
                 ->getQueryBuilderForTable($this->table);
 
-            if ($this->getEnvironmentMode() === 'FE') {
-                $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
-            }
-
             $result = $queryBuilder
                 ->select('*')
                 ->from($this->table)
@@ -153,16 +191,13 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
     {
         $this->initializeLocalCache();
 
-        /** @var Driver\DriverRegistry $driverRegistry */
-        $driverRegistry = GeneralUtility::makeInstance(DriverRegistry::class);
-
         $storageObjects = [];
         foreach ($this->storageRowCache as $storageRow) {
             if ($storageRow['driver'] !== $storageType) {
                 continue;
             }
-            if ($driverRegistry->driverExists($storageRow['driver'])) {
-                $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
+            if ($this->driverRegistry->driverExists($storageRow['driver'])) {
+                $storageObjects[] = $this->getStorageObject($storageRow['uid'], $storageRow);
             } else {
                 $this->logger->warning(
                     sprintf('Could not instantiate storage "%s" because of missing driver.', [$storageRow['name']]),
@@ -183,13 +218,10 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
     {
         $this->initializeLocalCache();
 
-        /** @var Driver\DriverRegistry $driverRegistry */
-        $driverRegistry = GeneralUtility::makeInstance(DriverRegistry::class);
-
         $storageObjects = [];
         foreach ($this->storageRowCache as $storageRow) {
-            if ($driverRegistry->driverExists($storageRow['driver'])) {
-                $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
+            if ($this->driverRegistry->driverExists($storageRow['driver'])) {
+                $storageObjects[] = $this->getStorageObject($storageRow['uid'], $storageRow);
             } else {
                 $this->logger->warning(
                     sprintf('Could not instantiate storage "%s" because of missing driver.', [$storageRow['name']]),
@@ -226,9 +258,7 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
             ]
         ];
 
-        /** @var FlexFormTools $flexObj */
-        $flexObj = GeneralUtility::makeInstance(FlexFormTools::class);
-        $flexFormXml = $flexObj->flexArray2Xml($flexFormData, true);
+        $flexFormXml = GeneralUtility::makeInstance(FlexFormTools::class)->flexArray2Xml($flexFormData, true);
 
         // create the record
         $field_values = [
@@ -256,17 +286,6 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
         return (int)$dbConnection->lastInsertId($this->table);
     }
 
-    /**
-     * Creates an object managed by this repository.
-     *
-     * @param array $databaseRow
-     * @return ResourceStorage
-     */
-    protected function createDomainObject(array $databaseRow)
-    {
-        return $this->factory->getStorageObject($databaseRow['uid'], $databaseRow);
-    }
-
     /**
      * Test if the local filesystem is case sensitive
      *
@@ -296,4 +315,169 @@ class StorageRepository extends AbstractRepository implements LoggerAwareInterfa
 
         return $caseSensitive;
     }
+
+    /**
+     * Creates an instance of the storage from given UID. The $recordData can
+     * be supplied to increase performance.
+     *
+     * @param int $uid The uid of the storage to instantiate.
+     * @param array $recordData The record row from database.
+     * @param mixed|null $fileIdentifier Identifier for a file. Used for auto-detection of a storage, but only if $uid === 0 (Local default storage) is used
+     * @throws \InvalidArgumentException
+     * @return ResourceStorage
+     */
+    public function getStorageObject($uid, array $recordData = [], &$fileIdentifier = null): ResourceStorage
+    {
+        if (!is_numeric($uid)) {
+            throw new \InvalidArgumentException('The UID of storage has to be numeric. UID given: "' . $uid . '"', 1314085991);
+        }
+        $uid = (int)$uid;
+        if ($uid === 0 && $fileIdentifier !== null) {
+            $uid = $this->findBestMatchingStorageByLocalPath($fileIdentifier);
+        }
+        if (empty($this->storageInstances[$uid])) {
+            $storageConfiguration = null;
+            $storageObject = null;
+            /** @var BeforeResourceStorageInitializationEvent $event */
+            $event = $this->eventDispatcher->dispatch(new BeforeResourceStorageInitializationEvent($uid, $recordData, $fileIdentifier));
+            $recordData = $event->getRecord();
+            $uid = $event->getStorageUid();
+            $fileIdentifier = $event->getFileIdentifier();
+            // If the built-in storage with UID=0 is requested:
+            if ($uid === 0) {
+                $recordData = [
+                    'uid' => 0,
+                    'pid' => 0,
+                    'name' => 'Fallback Storage',
+                    'description' => 'Internal storage, mounting the main TYPO3_site directory.',
+                    'driver' => 'Local',
+                    'processingfolder' => 'typo3temp/assets/_processed_/',
+                    // legacy code
+                    'configuration' => '',
+                    'is_online' => true,
+                    'is_browsable' => true,
+                    'is_public' => true,
+                    'is_writable' => true,
+                    'is_default' => false,
+                ];
+                $storageConfiguration = [
+                    'basePath' => '/',
+                    'pathType' => 'relative'
+                ];
+            } elseif ($recordData === [] || (int)$recordData['uid'] !== $uid) {
+                $recordData = $this->fetchRecordDataByUid($uid);
+            }
+            $storageObject = $this->createStorageObject($recordData, $storageConfiguration);
+            $storageObject = $this->eventDispatcher
+                ->dispatch(new AfterResourceStorageInitializationEvent($storageObject))
+                ->getStorage();
+            $this->storageInstances[$uid] = $storageObject;
+        }
+        return $this->storageInstances[$uid];
+    }
+
+    /**
+     * Checks whether a file resides within a real storage in local file system.
+     * If no match is found, uid 0 is returned which is a fallback storage pointing to fileadmin in public web path.
+     *
+     * The file identifier is adapted accordingly to match the new storage's base path.
+     *
+     * @param string $localPath
+     * @return int
+     */
+    protected function findBestMatchingStorageByLocalPath(&$localPath): int
+    {
+        if ($this->localDriverStorageCache === null) {
+            $this->initializeLocalStorageCache();
+        }
+
+        $bestMatchStorageUid = 0;
+        $bestMatchLength = 0;
+        foreach ($this->localDriverStorageCache as $storageUid => $basePath) {
+            $matchLength = strlen((string)PathUtility::getCommonPrefix([$basePath, $localPath]));
+            $basePathLength = strlen($basePath);
+
+            if ($matchLength >= $basePathLength && $matchLength > $bestMatchLength) {
+                $bestMatchStorageUid = (int)$storageUid;
+                $bestMatchLength = $matchLength;
+            }
+        }
+        if ($bestMatchStorageUid !== 0) {
+            $localPath = substr($localPath, $bestMatchLength);
+        }
+        return $bestMatchStorageUid;
+    }
+
+    /**
+     * Creates an array mapping all uids to the basePath of storages using the "local" driver.
+     */
+    protected function initializeLocalStorageCache(): void
+    {
+        $storageObjects = $this->findByStorageType('Local');
+
+        $storageCache = [];
+        foreach ($storageObjects as $localStorage) {
+            $configuration = $localStorage->getConfiguration();
+            $storageCache[$localStorage->getUid()] = $configuration['basePath'];
+        }
+        $this->localDriverStorageCache = $storageCache;
+    }
+
+    /**
+     * Creates a storage object from a storage database row.
+     *
+     * @param array $storageRecord
+     * @param array|null $storageConfiguration Storage configuration (if given, this won't be extracted from the FlexForm value but the supplied array used instead)
+     * @return ResourceStorage
+     * @internal this method is only public for having access to ResourceFactory->createStorageObject(). In TYPO3 v12 this method can be changed to protected again.
+     */
+    public function createStorageObject(array $storageRecord, array $storageConfiguration = null): ResourceStorage
+    {
+        if (!$storageConfiguration && !empty($storageRecord['configuration'])) {
+            $storageConfiguration = $this->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
+        }
+        $driverType = $storageRecord['driver'];
+        $driverObject = $this->getDriverObject($driverType, $storageConfiguration);
+        $storageRecord['configuration'] = $storageConfiguration;
+        return GeneralUtility::makeInstance(ResourceStorage::class, $driverObject, $storageRecord, $this->eventDispatcher);
+    }
+
+    /**
+     * Converts a flexform data string to a flat array with key value pairs
+     *
+     * @param string $flexFormData
+     * @return array Array with key => value pairs of the field data in the FlexForm
+     */
+    protected function convertFlexFormDataToConfigurationArray(string $flexFormData): array
+    {
+        if ($flexFormData) {
+            return GeneralUtility::makeInstance(FlexFormService::class)->convertFlexFormContentToArray($flexFormData);
+        }
+        return [];
+    }
+
+    /**
+     * Creates a driver object for a specified storage object.
+     *
+     * @param string $driverIdentificationString The driver class (or identifier) to use.
+     * @param array $driverConfiguration The configuration of the storage
+     * @return DriverInterface
+     */
+    protected function getDriverObject(string $driverIdentificationString, array $driverConfiguration): DriverInterface
+    {
+        $driverClass = $this->driverRegistry->getDriverClass($driverIdentificationString);
+        /** @var DriverInterface $driverObject */
+        $driverObject = GeneralUtility::makeInstance($driverClass, $driverConfiguration);
+        return $driverObject;
+    }
+
+    /**
+     * @param array $storageRecord
+     * @return ResourceStorage
+     * @internal
+     */
+    public function createFromRecord(array $storageRecord): ResourceStorage
+    {
+        return $this->createStorageObject($storageRecord);
+    }
 }
diff --git a/typo3/sysext/core/Classes/ServiceProvider.php b/typo3/sysext/core/Classes/ServiceProvider.php
index b2083eb43f3c6205333bf6f42b45a7b196ea6ba0..db4fd70a1a3748664273b2ba826f5f33d55b2a09 100644
--- a/typo3/sysext/core/Classes/ServiceProvider.php
+++ b/typo3/sysext/core/Classes/ServiceProvider.php
@@ -265,13 +265,16 @@ class ServiceProvider extends AbstractServiceProvider
     public static function getResourceFactory(ContainerInterface $container): Resource\ResourceFactory
     {
         return self::new($container, Resource\ResourceFactory::class, [
-            $container->get(EventDispatcherInterface::class)
+            $container->get(Resource\StorageRepository::class)
         ]);
     }
 
     public static function getStorageRepository(ContainerInterface $container): Resource\StorageRepository
     {
-        return self::new($container, Resource\StorageRepository::class);
+        return self::new($container, Resource\StorageRepository::class, [
+            $container->get(EventDispatcherInterface::class),
+            $container->get(Resource\Driver\DriverRegistry::class),
+        ]);
     }
 
     public static function getDependencyOrderingService(ContainerInterface $container): Service\DependencyOrderingService
diff --git a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php
index 2216cd5fba5d65106d7e4118a5bf22ce22d7136f..4037d029b2ca8ef9b07fda553cc2e2cae8fb9df2 100644
--- a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php
+++ b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php
@@ -1090,9 +1090,7 @@ class ExtendedFileUtility extends BasicFileUtility
                 'size' => $uploadedFileData['size'][$i]
             ];
             try {
-                /** @var File $fileObject */
                 $fileObject = $targetFolderObject->addUploadedFile($fileInfo, (string)$this->existingFilesConflictMode);
-                $fileObject = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectByStorageAndIdentifier($targetFolderObject->getStorage()->getUid(), $fileObject->getIdentifier());
                 if ($this->existingFilesConflictMode->equals(DuplicationBehavior::REPLACE)) {
                     $this->getIndexer($fileObject->getStorage())->updateIndexEntry($fileObject);
                 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-92289-DecoupleLogicOfResourceFactoryIntoStorageRepository.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-92289-DecoupleLogicOfResourceFactoryIntoStorageRepository.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e7a0e3e181f318453736615e4a2499a3f8fb1e4c
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-92289-DecoupleLogicOfResourceFactoryIntoStorageRepository.rst
@@ -0,0 +1,64 @@
+.. include:: ../../Includes.txt
+
+===========================================================================
+Breaking: #92289 - Decouple logic of ResourceFactory into StorageRepository
+===========================================================================
+
+See :issue:`92289`
+
+Description
+===========
+
+The ResourceFactory was initially created for the File Abstraction Layer (FAL)
+as a Factory class, which created PHP objects.
+
+However, in the recent years, it became more apparent that it is more useful to
+separate the concerns of the creation and retrieving of existing information.
+
+For this reason, the StorageRepository is now handling the creation of
+ResourceStorage objects. This layer accesses the Database and the needed Driver
+objects and configuration.
+
+The StorageRepository class does not extend from AbstractRepository anymore,
+and is available standalone.
+
+Most of the logic in the ResourceFactory concerning Storages has been moved to
+StorageRepository, which has a lot of options available now.
+
+The following methods within ResourceFactory have been marked
+as internal, and are kept for backwards-compatibility without deprecation:
+
+* :php:`ResourceFactory->getDefaultStorage()`
+* :php:`ResourceFactory->getStorageObject()`
+* :php:`ResourceFactory->convertFlexFormDataToConfigurationArray()`
+* :php:`ResourceFactory->createStorageObject()`
+* :php:`ResourceFactory->createFolderObject()`
+* :php:`ResourceFactory->getFileObjectByStorageAndIdentifier()`
+* :php:`ResourceFactory->getStorageObjectFromCombinedIdentifier()`
+
+The following method has been removed
+* :php:`ResourceFactory->getDriverObject()`
+
+
+Impact
+======
+
+Calling the removed method will throw a fatal error.
+
+Checking StorageRepository for an instance of AbstractRepository
+will have different results.
+
+
+Affected Installations
+======================
+
+TYPO3 installations with specific third-party extensions working with the FAL
+API directly might use the existing functionality.
+
+
+Migration
+=========
+
+Migrate to the StorageRepository API in the third-party extension code.
+
+.. index:: FAL, PHP-API, FullyScanned, ext:core
diff --git a/typo3/sysext/core/Tests/Functional/Resource/ResourceStorageTest.php b/typo3/sysext/core/Tests/Functional/Resource/ResourceStorageTest.php
index 4006006ff299744012482245c9b9be9162109fab..04ef0f206412a0170e6bbe004cfc22e98bb42faf 100644
--- a/typo3/sysext/core/Tests/Functional/Resource/ResourceStorageTest.php
+++ b/typo3/sysext/core/Tests/Functional/Resource/ResourceStorageTest.php
@@ -47,7 +47,7 @@ class ResourceStorageTest extends FunctionalTestCase
     {
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
         $subject->setEvaluatePermissions(false);
 
         GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/_processed_');
@@ -93,7 +93,7 @@ class ResourceStorageTest extends FunctionalTestCase
         clearstatcache();
         $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/' . $targetDirectory . '/' . $fileName);
 
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
         $subject->setEvaluatePermissions(true);
 
         // read_only = true -> no write access for user, so checking for second argument true should assert false
@@ -160,7 +160,7 @@ class ResourceStorageTest extends FunctionalTestCase
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
 
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
         $processingFolder = $subject->getProcessingFolder();
 
         self::assertInstanceOf(Folder::class, $processingFolder);
@@ -175,7 +175,7 @@ class ResourceStorageTest extends FunctionalTestCase
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
 
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
         $folder = new Folder($subject, '/foo/' . $folderIdentifier . '/', $folderIdentifier);
 
         $role = $subject->getRole($folder);
@@ -190,7 +190,7 @@ class ResourceStorageTest extends FunctionalTestCase
     {
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
 
         GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/foo');
         file_put_contents(Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'myData');
@@ -209,7 +209,7 @@ class ResourceStorageTest extends FunctionalTestCase
     {
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
 
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1325689164);
@@ -223,7 +223,7 @@ class ResourceStorageTest extends FunctionalTestCase
     {
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
 
         GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/foo');
         GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/_recycler_');
@@ -244,7 +244,7 @@ class ResourceStorageTest extends FunctionalTestCase
     {
         $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
         $this->setUpBackendUserFromFixture(1);
-        $subject = (new StorageRepository())->findByUid(1);
+        $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
 
         GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/foo');
         file_put_contents(Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'myData');
@@ -394,7 +394,7 @@ class ResourceStorageTest extends FunctionalTestCase
             $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
             $this->importDataSet(__DIR__ . '/Fixtures/FileSearch.xml');
             $this->setUpBackendUserFromFixture(1);
-            $subject = (new StorageRepository())->findByUid(1);
+            $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
             $subject->setFileAndFolderNameFilters($filters);
 
             GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/fileadmin/bar/bla');
diff --git a/typo3/sysext/core/Tests/Unit/Resource/FileTest.php b/typo3/sysext/core/Tests/Unit/Resource/FileTest.php
index 2479ceed0e6b699760206bc2457fbf8fd2b9126a..7582c1627e3d74f911bebe8e0d5cc568670f86b7 100644
--- a/typo3/sysext/core/Tests/Unit/Resource/FileTest.php
+++ b/typo3/sysext/core/Tests/Unit/Resource/FileTest.php
@@ -21,8 +21,8 @@ use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\Index\MetaDataRepository;
 use TYPO3\CMS\Core\Resource\MetaDataAspect;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
@@ -166,12 +166,12 @@ class FileTest extends UnitTestCase
             ->setConstructorArgs([$fileProperties, $this->storageMock])
             ->getMock();
         $mockedNewStorage = $this->createMock(ResourceStorage::class);
-        $mockedResourceFactory = $this->createMock(ResourceFactory::class);
-        $mockedResourceFactory
+        $mockedStorageRepository = $this->createMock(StorageRepository::class);
+        $mockedStorageRepository
             ->expects(self::once())
-            ->method('getStorageObject')
+            ->method('findByUid')
             ->willReturn($mockedNewStorage);
-        GeneralUtility::setSingletonInstance(ResourceFactory::class, $mockedResourceFactory);
+        GeneralUtility::addInstance(StorageRepository::class, $mockedStorageRepository);
 
         $subject->updateProperties(['storage' => 'different']);
         self::assertSame($mockedNewStorage, $subject->getStorage());
diff --git a/typo3/sysext/core/Tests/Unit/Resource/ResourceFactoryTest.php b/typo3/sysext/core/Tests/Unit/Resource/ResourceFactoryTest.php
index 051e2727e776340e4626e031531a3e7785cad227..83532bc5f343775415f383d3a8f7235629201706 100644
--- a/typo3/sysext/core/Tests/Unit/Resource/ResourceFactoryTest.php
+++ b/typo3/sysext/core/Tests/Unit/Resource/ResourceFactoryTest.php
@@ -15,10 +15,7 @@
 
 namespace TYPO3\CMS\Core\Tests\Unit\Resource;
 
-use Psr\EventDispatcher\EventDispatcherInterface;
 use TYPO3\CMS\Core\Core\Environment;
-use TYPO3\CMS\Core\Resource\Driver\AbstractDriver;
-use TYPO3\CMS\Core\Resource\Driver\DriverRegistry;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -65,39 +62,18 @@ class ResourceFactoryTest extends UnitTestCase
         parent::tearDown();
     }
 
-    /**********************************
-     * Storage Collections
-     **********************************/
     /**
      * @test
      */
-    public function createStorageCollectionObjectCreatesCollectionWithCorrectArguments()
+    public function createFolderCreatesObjectWithCorrectArguments()
     {
         $mockedMount = $this->createMock(ResourceStorage::class);
         $path = StringUtility::getUniqueId('path_');
         $name = StringUtility::getUniqueId('name_');
-        $storageCollection = $this->subject->createFolderObject($mockedMount, $path, $name, 0);
-        self::assertSame($mockedMount, $storageCollection->getStorage());
-        self::assertEquals($path, $storageCollection->getIdentifier());
-        self::assertEquals($name, $storageCollection->getName());
-    }
-
-    /**********************************
-     * Drivers
-     **********************************/
-    /**
-     * @test
-     */
-    public function getDriverObjectAcceptsDriverClassName()
-    {
-        $mockedDriver = $this->getMockForAbstractClass(AbstractDriver::class);
-        $driverFixtureClass = get_class($mockedDriver);
-        GeneralUtility::addInstance($driverFixtureClass, $mockedDriver);
-        $mockedRegistry = $this->createMock(DriverRegistry::class);
-        $mockedRegistry->expects(self::once())->method('getDriverClass')->with(self::equalTo($driverFixtureClass))->willReturn($driverFixtureClass);
-        GeneralUtility::setSingletonInstance(DriverRegistry::class, $mockedRegistry);
-        $obj = $this->subject->getDriverObject($driverFixtureClass, []);
-        self::assertInstanceOf(AbstractDriver::class, $obj);
+        $folderObject = $this->subject->createFolderObject($mockedMount, $path, $name);
+        self::assertSame($mockedMount, $folderObject->getStorage());
+        self::assertEquals($path, $folderObject->getIdentifier());
+        self::assertEquals($name, $folderObject->getName());
     }
 
     /***********************************
@@ -159,74 +135,4 @@ class ResourceFactoryTest extends UnitTestCase
         $this->filesCreated[] = Environment::getPublicPath() . '/' . $filename;
         $this->subject->retrieveFileOrFolderObject($filename);
     }
-
-    /***********************************
-     * Storage AutoDetection
-     ***********************************/
-
-    /**
-     * @param array $storageConfiguration
-     * @param string $path
-     * @param int $expectedStorageId
-     * @test
-     * @dataProvider storageDetectionDataProvider
-     */
-    public function findBestMatchingStorageByLocalPathReturnsDefaultStorageIfNoMatchIsFound(array $storageConfiguration, $path, $expectedStorageId)
-    {
-        $resourceFactory = new ResourceFactory($this->prophesize(EventDispatcherInterface::class)->reveal());
-        $mock = \Closure::bind(static function (ResourceFactory $resourceFactory) use (&$path, $storageConfiguration) {
-            $resourceFactory->localDriverStorageCache = $storageConfiguration;
-            return $resourceFactory->findBestMatchingStorageByLocalPath($path);
-        }, null, ResourceFactory::class);
-        self::assertSame($expectedStorageId, $mock($resourceFactory));
-    }
-
-    /**
-     * @return array
-     */
-    public function storageDetectionDataProvider()
-    {
-        return [
-            'NoLocalStoragesReturnDefaultStorage' => [
-                [],
-                'my/dummy/Image.png',
-                0
-            ],
-            'NoMatchReturnsDefaultStorage' => [
-                [1 => 'fileadmin/', 2 => 'fileadmin2/public/'],
-                'my/dummy/Image.png',
-                0
-            ],
-            'MatchReturnsTheMatch' => [
-                [1 => 'fileadmin/', 2 => 'other/public/'],
-                'fileadmin/dummy/Image.png',
-                1
-            ],
-            'TwoFoldersWithSameStartReturnsCorrect' => [
-                [1 => 'fileadmin/', 2 => 'fileadmin/public/'],
-                'fileadmin/dummy/Image.png',
-                1
-            ],
-            'NestedStorageReallyReturnsTheBestMatching' => [
-                [1 => 'fileadmin/', 2 => 'fileadmin/public/'],
-                'fileadmin/public/Image.png',
-                2
-            ],
-            'CommonPrefixButWrongPath' => [
-                [1 => 'fileadmin/', 2 => 'uploads/test/'],
-                'uploads/bogus/dummy.png',
-                0
-            ],
-            'CommonPrefixRightPath' => [
-                [1 => 'fileadmin/', 2 => 'uploads/test/'],
-                'uploads/test/dummy.png',
-                2
-            ],
-            'FindStorageFromWindowsPath' => [
-                [1 => 'fileadmin/', 2 => 'uploads/test/'],
-                'uploads\\test\\dummy.png',
-                2
-            ],
-        ];
-    }
 }
diff --git a/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php b/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
index 55527c40d78740cfde098aa160775f6816e892ce..683b8df18728c0d5173b39d1eca2c2a989161400 100644
--- a/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
+++ b/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
@@ -836,16 +836,15 @@ class ResourceStorageTest extends BaseTestCase
             'bar',
             'bar_01'
         ));
-        $resourceFactory = $this->createMock(ResourceFactory::class);
         $this->prepareSubject(
             [],
             true,
             $mockedDriver,
-            $resourceFactory,
+            null,
             [],
-            ['getUniqueName']
+            ['getUniqueName', 'createFolderObject']
         );
-        $resourceFactory->expects(self::once())->method('createFolderObject')->willReturn(new Folder($this->subject, '', ''));
+        $this->subject->expects(self::once())->method('createFolderObject')->willReturn(new Folder($this->subject, '', ''));
         /** @var File $file */
         $file = new File(['identifier' => 'foo', 'name' => 'foo'], $this->subject);
         $this->subject->expects(self::any())->method('getUniqueName')->willReturn('bar_01');
diff --git a/typo3/sysext/core/Tests/Unit/Resource/StorageRepositoryTest.php b/typo3/sysext/core/Tests/Unit/Resource/StorageRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..54828cfdcde912fd57bff892def9c547ffe02212
--- /dev/null
+++ b/typo3/sysext/core/Tests/Unit/Resource/StorageRepositoryTest.php
@@ -0,0 +1,127 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Unit\Resource;
+
+use Psr\EventDispatcher\EventDispatcherInterface;
+use TYPO3\CMS\Core\Resource\Driver\AbstractDriver;
+use TYPO3\CMS\Core\Resource\Driver\DriverRegistry;
+use TYPO3\CMS\Core\Resource\StorageRepository;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class StorageRepositoryTest extends UnitTestCase
+{
+    /**********************************
+     * Drivers
+     **********************************/
+    /**
+     * @test
+     */
+    public function getDriverObjectAcceptsDriverClassName()
+    {
+        $mockedDriver = $this->getMockForAbstractClass(AbstractDriver::class);
+        $driverFixtureClass = get_class($mockedDriver);
+        $registry = new DriverRegistry();
+        $registry->registerDriverClass($driverFixtureClass);
+        $subject = $this->getAccessibleMock(
+            StorageRepository::class,
+            ['dummy'],
+            [
+                $this->prophesize(EventDispatcherInterface::class)->reveal(),
+                $registry
+            ]
+        );
+        $obj = $subject->_call('getDriverObject', $driverFixtureClass, []);
+        self::assertInstanceOf(AbstractDriver::class, $obj);
+    }
+
+    /***********************************
+     * Storage AutoDetection
+     ***********************************/
+
+    /**
+     * @param array $storageConfiguration
+     * @param string $path
+     * @param int $expectedStorageId
+     * @test
+     * @dataProvider storageDetectionDataProvider
+     */
+    public function findBestMatchingStorageByLocalPathReturnsDefaultStorageIfNoMatchIsFound(array $storageConfiguration, $path, $expectedStorageId)
+    {
+        $subject = new StorageRepository(
+            $this->prophesize(EventDispatcherInterface::class)->reveal(),
+            $this->prophesize(DriverRegistry::class)->reveal()
+        );
+        $mock = \Closure::bind(static function (StorageRepository $storageRepository) use (&$path, $storageConfiguration) {
+            $storageRepository->localDriverStorageCache = $storageConfiguration;
+            return $storageRepository->findBestMatchingStorageByLocalPath($path);
+        }, null, StorageRepository::class);
+        self::assertSame($expectedStorageId, $mock($subject));
+    }
+
+    /**
+     * @return array
+     */
+    public function storageDetectionDataProvider()
+    {
+        return [
+            'NoLocalStoragesReturnDefaultStorage' => [
+                [],
+                'my/dummy/Image.png',
+                0
+            ],
+            'NoMatchReturnsDefaultStorage' => [
+                [1 => 'fileadmin/', 2 => 'fileadmin2/public/'],
+                'my/dummy/Image.png',
+                0
+            ],
+            'MatchReturnsTheMatch' => [
+                [1 => 'fileadmin/', 2 => 'other/public/'],
+                'fileadmin/dummy/Image.png',
+                1
+            ],
+            'TwoFoldersWithSameStartReturnsCorrect' => [
+                [1 => 'fileadmin/', 2 => 'fileadmin/public/'],
+                'fileadmin/dummy/Image.png',
+                1
+            ],
+            'NestedStorageReallyReturnsTheBestMatching' => [
+                [1 => 'fileadmin/', 2 => 'fileadmin/public/'],
+                'fileadmin/public/Image.png',
+                2
+            ],
+            'CommonPrefixButWrongPath' => [
+                [1 => 'fileadmin/', 2 => 'uploads/test/'],
+                'uploads/bogus/dummy.png',
+                0
+            ],
+            'CommonPrefixRightPath' => [
+                [1 => 'fileadmin/', 2 => 'uploads/test/'],
+                'uploads/test/dummy.png',
+                2
+            ],
+            'FindStorageFromWindowsPath' => [
+                [1 => 'fileadmin/', 2 => 'uploads/test/'],
+                'uploads\\test\\dummy.png',
+                2
+            ],
+        ];
+    }
+}
diff --git a/typo3/sysext/filelist/Classes/Controller/FileListController.php b/typo3/sysext/filelist/Classes/Controller/FileListController.php
index 5191b6a69562f7730f71a420945d840eba5fe62f..1fcaa5ebe8fd4f6046de33d3ed8be1ccd968ba66 100644
--- a/typo3/sysext/filelist/Classes/Controller/FileListController.php
+++ b/typo3/sysext/filelist/Classes/Controller/FileListController.php
@@ -35,6 +35,7 @@ use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Resource\Search\FileSearchDemand;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Resource\Utility\ListUtility;
 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
 use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
@@ -173,14 +174,12 @@ class FileListController extends ActionController implements LoggerAwareInterfac
         try {
             if ($combinedIdentifier) {
                 $this->getBackendUser()->evaluateUserSpecificFileFilterSettings();
-                $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
-                $storage = $resourceFactory->getStorageObjectFromCombinedIdentifier($combinedIdentifier);
+                $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByCombinedIdentifier($combinedIdentifier);
                 $identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1);
                 if (!$storage->hasFolder($identifier)) {
                     $identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier);
                 }
-
-                $this->folderObject = $resourceFactory->getFolderObjectFromCombinedIdentifier($storage->getUid() . ':' . $identifier);
+                $this->folderObject = $storage->getFolder($identifier);
                 // Disallow access to fallback storage 0
                 if ($storage->getUid() === 0) {
                     throw new InsufficientFolderAccessPermissionsException(
diff --git a/typo3/sysext/form/Tests/Functional/Hooks/FormFileExtensionUpdateTest.php b/typo3/sysext/form/Tests/Functional/Hooks/FormFileExtensionUpdateTest.php
index fb1efde8bbd6ee422f4e4ede5900bf491b040fa8..f33adedd0c5316920b8608eef86e7a23ff85e8e1 100644
--- a/typo3/sysext/form/Tests/Functional/Hooks/FormFileExtensionUpdateTest.php
+++ b/typo3/sysext/form/Tests/Functional/Hooks/FormFileExtensionUpdateTest.php
@@ -24,7 +24,7 @@ use TYPO3\CMS\Core\Core\Bootstrap;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\ReferenceIndex;
 use TYPO3\CMS\Core\Resource\Folder;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
@@ -81,7 +81,7 @@ class FormFileExtensionUpdateTest extends FunctionalTestCase
         Bootstrap::initializeLanguageObject();
 
         $folderIdentifier = 'form_definitions';
-        $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject(1);
+        $storage = GeneralUtility::makeInstance(StorageRepository::class)->getStorageObject(1);
 
         if ($storage->hasFolder($folderIdentifier)) {
             $storage->getFolder($folderIdentifier)->delete(true);
diff --git a/typo3/sysext/frontend/Tests/Functional/Imaging/GifBuilderTest.php b/typo3/sysext/frontend/Tests/Functional/Imaging/GifBuilderTest.php
index 8436de9f8ea83783eaa636478c34f865b8169cf3..07cfdc9596b5a7e550dc5a49181445f76142b25b 100644
--- a/typo3/sysext/frontend/Tests/Functional/Imaging/GifBuilderTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/Imaging/GifBuilderTest.php
@@ -19,6 +19,7 @@ namespace TYPO3\CMS\Frontend\Tests\Functional\Imaging;
 
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Resource\StorageRepository;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Imaging\GifBuilder;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
@@ -42,7 +43,7 @@ class GifBuilderTest extends FunctionalTestCase
             Environment::getPublicPath() . '/fileadmin/kasper-skarhoj1.jpg'
         );
 
-        $storageRepository = (new StorageRepository())->findByUid(1);
+        $storageRepository = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
         $file = $storageRepository->getFile('kasper-skarhoj1.jpg');
 
         self::assertFalse($file->isMissing());
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php
index bc6eac335cc43e378c6eebd283af02020dd9b75b..d3651e20a10f4de2ecda7ab72085d800fd6c68e9 100644
--- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php
@@ -126,7 +126,7 @@ class TypoLinkGeneratorTest extends AbstractTestCase
      */
     private function setUpFileStorage()
     {
-        $storageRepository = new StorageRepository();
+        $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
         $storageId = $storageRepository->createLocalStorage(
             'fileadmin',
             'fileadmin/',
diff --git a/typo3/sysext/impexp/Classes/Import.php b/typo3/sysext/impexp/Classes/Import.php
index faa726f72c10694131b63d9584c1a20804a9b8f5..1f1d470a54b24905373a23161f859a50c46ea581 100644
--- a/typo3/sysext/impexp/Classes/Import.php
+++ b/typo3/sysext/impexp/Classes/Import.php
@@ -28,6 +28,7 @@ use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Resource\Security\FileNameValidator;
 use TYPO3\CMS\Core\Resource\StorageRepository;
+use TYPO3\CMS\Core\Service\FlexFormService;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -219,7 +220,7 @@ class Import extends ImportExport
 
         $defaultStorageUid = null;
         // get default storage
-        $defaultStorage = GeneralUtility::makeInstance(ResourceFactory::class)->getDefaultStorage();
+        $defaultStorage = GeneralUtility::makeInstance(StorageRepository::class)->getDefaultStorage();
         if ($defaultStorage !== null) {
             $defaultStorageUid = $defaultStorage->getUid();
         }
@@ -246,7 +247,7 @@ class Import extends ImportExport
             && (bool)$storageObject->isWritable() === (bool)$storageRecord['is_writable']
             && (bool)$storageObject->isOnline() === (bool)$storageRecord['is_online']
         ) {
-            $storageRecordConfiguration = GeneralUtility::makeInstance(ResourceFactory::class)->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
+            $storageRecordConfiguration = GeneralUtility::makeInstance(FlexFormService::class)->convertFlexFormContentToArray($storageRecord['configuration'] ?? '');
             $storageObjectConfiguration = $storageObject->getConfiguration();
             // compare the properties: pathType and basePath
             if ($storageRecordConfiguration['pathType'] === $storageObjectConfiguration['pathType']
@@ -305,7 +306,7 @@ class Import extends ImportExport
                         // storage object will check whether the target folder exists and set the
                         // isOnline flag depending on the outcome.
                         $storageRecord['uid'] = 0;
-                        $resourceStorage = GeneralUtility::makeInstance(ResourceFactory::class)->createStorageObject($storageRecord);
+                        $resourceStorage = GeneralUtility::makeInstance(StorageRepository::class)->createStorageObject($storageRecord);
                         if (!$resourceStorage->isOnline()) {
                             $configuration = $resourceStorage->getConfiguration();
                             $messages['resourceStorageFolderMissing_' . $storageRecordUid] =
@@ -335,7 +336,7 @@ class Import extends ImportExport
         // fetch fresh storage records from database
         $storageRecords = $this->fetchStorageRecords();
 
-        $defaultStorage = GeneralUtility::makeInstance(ResourceFactory::class)->getDefaultStorage();
+        $defaultStorage = GeneralUtility::makeInstance(StorageRepository::class)->getDefaultStorage();
 
         $sanitizedFolderMappings = [];
 
@@ -379,9 +380,9 @@ class Import extends ImportExport
             // mapping. Only in this case we could be sure, that it's a local, online and writable storage.
             if ($useStorageFromStorageRecords && isset($storageRecords[$fileRecord['storage']])) {
                 /** @var \TYPO3\CMS\Core\Resource\ResourceStorage $storage */
-                $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($fileRecord['storage'], $storageRecords[$fileRecord['storage']]);
+                $storage = GeneralUtility::makeInstance(StorageRepository::class)->getStorageObject($fileRecord['storage'], $storageRecords[$fileRecord['storage']]);
             } elseif ($this->isFallbackStorage($fileRecord['storage'])) {
-                $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject(0);
+                $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(0);
             } elseif ($defaultStorage !== null) {
                 $storage = $defaultStorage;
             } else {
diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
index 786b02a316a90690855b4f4ea27cc93d2354b100..83821fb4cb132433ac3dcf57d832da8bf5510cf5 100644
--- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
+++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
@@ -4493,4 +4493,11 @@ return [
             'Deprecation-92132-DeprecatedShortcutPHPAPI.rst'
         ],
     ],
+    'TYPO3\CMS\Core\Resource\ResourceFactory->getDriverObject' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Breaking-92289-DecoupleLogicOfResourceFactoryIntoStorageRepository.rst'
+        ],
+    ],
 ];
diff --git a/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionAdditionalFieldProvider.php b/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionAdditionalFieldProvider.php
index 5bf48ab3525c85a3bbe7c97c168b251255a1ce73..2f8be8c4119596e1827e84aa4bfd5dd9c32a76ec 100644
--- a/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionAdditionalFieldProvider.php
+++ b/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionAdditionalFieldProvider.php
@@ -17,7 +17,6 @@ namespace TYPO3\CMS\Scheduler\Task;
 
 use TYPO3\CMS\Core\Resource\Index\ExtractorInterface;
 use TYPO3\CMS\Core\Resource\Index\ExtractorRegistry;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -163,7 +162,7 @@ class FileStorageExtractionAdditionalFieldProvider implements AdditionalFieldPro
         ) {
             return false;
         }
-        if (GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($submittedData['scheduler_fileStorageIndexing_storage']) === null) {
+        if (GeneralUtility::makeInstance(StorageRepository::class)->findByUid($submittedData['scheduler_fileStorageIndexing_storage']) === null) {
             return false;
         }
         if (!MathUtility::isIntegerInRange($submittedData['scheduler_fileStorageIndexing_fileCount'], 1, 9999)) {
diff --git a/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionTask.php b/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionTask.php
index 1ad0059a807d2130da06672ffc3307135a717154..0d2cb90084440dcbc02ffcb4070b32bdc4d54b3e 100644
--- a/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionTask.php
+++ b/typo3/sysext/scheduler/Classes/Task/FileStorageExtractionTask.php
@@ -16,8 +16,8 @@
 namespace TYPO3\CMS\Scheduler\Task;
 
 use TYPO3\CMS\Core\Resource\Index\Indexer;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -49,7 +49,7 @@ class FileStorageExtractionTask extends AbstractTask
     {
         $success = false;
         if ((int)$this->storageUid > 0) {
-            $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($this->storageUid);
+            $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid($this->storageUid);
             $currentEvaluatePermissionsValue = $storage->getEvaluatePermissions();
             $storage->setEvaluatePermissions(false);
             $indexer = $this->getIndexer($storage);
diff --git a/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingAdditionalFieldProvider.php b/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingAdditionalFieldProvider.php
index 2d38b08e8518723f096338433c14b5c0b82eb0b6..67f7426773cca4328328aab2d8b01adc5c5d00d4 100644
--- a/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingAdditionalFieldProvider.php
+++ b/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingAdditionalFieldProvider.php
@@ -15,7 +15,6 @@
 
 namespace TYPO3\CMS\Scheduler\Task;
 
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -95,7 +94,7 @@ class FileStorageIndexingAdditionalFieldProvider implements AdditionalFieldProvi
         if (!MathUtility::canBeInterpretedAsInteger($value)) {
             return false;
         }
-        if (GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($submittedData['scheduler_fileStorageIndexing_storage']) !== null) {
+        if (GeneralUtility::makeInstance(StorageRepository::class)->findByUid($submittedData['scheduler_fileStorageIndexing_storage']) !== null) {
             return true;
         }
         return false;
diff --git a/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingTask.php b/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingTask.php
index 6ff91cbafd6d22271d917538595ac47147cb5767..175dc630cafd92e7347903a748d167ffefd1d572 100644
--- a/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingTask.php
+++ b/typo3/sysext/scheduler/Classes/Task/FileStorageIndexingTask.php
@@ -16,8 +16,8 @@
 namespace TYPO3\CMS\Scheduler\Task;
 
 use TYPO3\CMS\Core\Resource\Index\Indexer;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
+use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -41,7 +41,7 @@ class FileStorageIndexingTask extends AbstractTask
     public function execute()
     {
         if ((int)$this->storageUid > 0) {
-            $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($this->storageUid);
+            $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid($this->storageUid);
             $currentEvaluatePermissionsValue = $storage->getEvaluatePermissions();
             $storage->setEvaluatePermissions(false);
             $indexer = $this->getIndexer($storage);