diff --git a/app/api/controller/XunFeiController.php b/app/api/controller/XunFeiController.php
index 60db8ac44..fb0074293 100644
--- a/app/api/controller/XunFeiController.php
+++ b/app/api/controller/XunFeiController.php
@@ -122,18 +122,24 @@ class XunFeiController extends BaseApiController
     public function iat()
     {
         header('X-Accel-Buffering: no');
-        $st = microtime(true);
-
+        $file = request()->file('audio');
+        if(empty($file)){
+            return $this->fail('未上传音频文件');
+        }
+        // 上传到本地服务器
+        $savename = \think\facade\Filesystem::putFile('audio', $file);
+        $file = app()->getRootPath() .'/runtime/storage/' . $savename;
+        // $file = "https://lihai001.oss-cn-chengdu.aliyuncs.com/media/iat_mp3_16k.mp3";
+        $audioFile = fopen($file, 'rb');
+        if ($audioFile === false) {
+            return $this->fail('音频文件异常');
+        }
         $iatHostUrl = "wss://iat-api.xfyun.cn/v2/iat";
         $iat = new IatClient($this->app_id,$this->api_key,$this->api_secret);
-        // halt($iat->assembleAuthUrl($iatHostUrl));
         $client = new Client($iat->assembleAuthUrl($iatHostUrl));
         if ($client) {
-            // $file = app()->getRuntimePath() . 'iat_mp3_16k.mp3';
-            $file = "https://lihai001.oss-cn-chengdu.aliyuncs.com/media/iat_mp3_16k.mp3";
-            $audioFile = fopen($file, 'rb');
             $frameSize = 1280; //每一帧的音频大小
-            $intervel = 40 * 1000; //发送音频间隔
+            $intervel = 20 * 1000; //发送音频间隔
             $status = 0;
             while (true) {
                 $len = fread($audioFile, $frameSize);
@@ -143,7 +149,6 @@ class XunFeiController extends BaseApiController
                 if ($len === '') { //文件读取完了
                     $status = 2;
                 }
-    
                 switch ($status) {
                     case 0: //发送第一帧音频,带business 参数
                         $frameData = array(
@@ -188,11 +193,10 @@ class XunFeiController extends BaseApiController
                         $client->send(json_encode($frameData));
                         break 2;
                 }
-    
                 //模拟音频采样间隔
                 usleep($intervel);
             }
-
+            $words = '';
             while (true) {
                 $response = $client->receive();
                 if ($response === null) {
@@ -204,24 +208,25 @@ class XunFeiController extends BaseApiController
                 $data = $resp['data'];
                 $result = $data['result'];
                 $status = $data['status'];
-                $sid = $resp['sid'];
-    
+                foreach($result['ws'] as $v) {
+                    $words .= $v['cw'][0]['w'] ?? '';
+                }
                 if ($code != 0) {
-                    // echo sprintf('%d %s %f', $code, $message, microtime(true) - $st);
                     break;
                 }
-    
-                echo json_encode($result);
                 if ($status === 2) {
-                    // echo sprintf('%d %s %f', $code, $message, microtime(true) - $st);
                     break;
                 }
             }
         } else {
             return $this->fail('无法连接到 WebSocket 服务器');
         }
-
         fclose($audioFile);
+        // 删除临时音频文件
+        if (file_exists($file)) {
+            unlink($file);
+        }
+        return $this->data(['words' => $words]);
     }
 
 
diff --git a/composer.json b/composer.json
index 6a54ed941..1629869c5 100755
--- a/composer.json
+++ b/composer.json
@@ -41,7 +41,8 @@
         "textalk/websocket": "^1.6",
         "workerman/gateway-worker": "^3.1",
         "workerman/gatewayclient": "^3.0",
-        "jpush/jpush": "^3.6"
+        "jpush/jpush": "^3.6",
+        "topthink/think-filesystem": "^2.0"
     },
     "require-dev": {
         "symfony/var-dumper": "^4.2",
diff --git a/composer.lock b/composer.lock
index a9b49ff39..476d0f8ce 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "3d92336e839a1dff749e580808bfaa0a",
+    "content-hash": "d25d7e585d92ff404a5aaad86a120d75",
     "packages": [
         {
             "name": "adbario/php-dot-notation",
@@ -1083,6 +1083,160 @@
             },
             "time": "2021-08-12T07:43:39+00:00"
         },
+        {
+            "name": "league/flysystem",
+            "version": "2.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/thephpleague/flysystem.git",
+                "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8aaffb653c5777781b0f7f69a5d937baf7ab6cdb",
+                "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "league/mime-type-detection": "^1.0.0",
+                "php": "^7.2 || ^8.0"
+            },
+            "conflict": {
+                "guzzlehttp/ringphp": "<1.1.1"
+            },
+            "require-dev": {
+                "async-aws/s3": "^1.5",
+                "async-aws/simple-s3": "^1.0",
+                "aws/aws-sdk-php": "^3.132.4",
+                "composer/semver": "^3.0",
+                "ext-fileinfo": "*",
+                "ext-ftp": "*",
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "google/cloud-storage": "^1.23",
+                "phpseclib/phpseclib": "^2.0",
+                "phpstan/phpstan": "^0.12.26",
+                "phpunit/phpunit": "^8.5 || ^9.4",
+                "sabre/dav": "^4.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "League\\Flysystem\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frankdejonge.nl"
+                }
+            ],
+            "description": "File storage abstraction for PHP",
+            "keywords": [
+                "WebDAV",
+                "aws",
+                "cloud",
+                "file",
+                "files",
+                "filesystem",
+                "filesystems",
+                "ftp",
+                "s3",
+                "sftp",
+                "storage"
+            ],
+            "support": {
+                "issues": "https://github.com/thephpleague/flysystem/issues",
+                "source": "https://github.com/thephpleague/flysystem/tree/2.5.0"
+            },
+            "funding": [
+                {
+                    "url": "https://ecologi.com/frankdejonge",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/frankdejonge",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-09-17T21:02:32+00:00"
+        },
+        {
+            "name": "league/mime-type-detection",
+            "version": "1.13.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/thephpleague/mime-type-detection.git",
+                "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96",
+                "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-fileinfo": "*",
+                "php": "^7.4 || ^8.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "phpstan/phpstan": "^0.12.68",
+                "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "League\\MimeTypeDetection\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frankdejonge.nl"
+                }
+            ],
+            "description": "Mime-type detection for Flysystem",
+            "support": {
+                "issues": "https://github.com/thephpleague/mime-type-detection/issues",
+                "source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/frankdejonge",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-08-05T12:09:49+00:00"
+        },
         {
             "name": "maennchen/zipstream-php",
             "version": "2.4.0",
@@ -4696,6 +4850,58 @@
             },
             "time": "2023-07-11T15:16:03+00:00"
         },
+        {
+            "name": "topthink/think-filesystem",
+            "version": "v2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-filesystem.git",
+                "reference": "c08503232fcae0c3c7fefae5e6b5c841ffe09f2f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/c08503232fcae0c3c7fefae5e6b5c841ffe09f2f",
+                "reference": "c08503232fcae0c3c7fefae5e6b5c841ffe09f2f",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "league/flysystem": "^2.0",
+                "topthink/framework": "^6.1|^8.0"
+            },
+            "require-dev": {
+                "mikey179/vfsstream": "^1.6",
+                "mockery/mockery": "^1.2",
+                "phpunit/phpunit": "^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP6.1 Filesystem Package",
+            "support": {
+                "issues": "https://github.com/top-think/think-filesystem/issues",
+                "source": "https://github.com/top-think/think-filesystem/tree/v2.0.2"
+            },
+            "time": "2023-02-08T01:23:42+00:00"
+        },
         {
             "name": "topthink/think-helper",
             "version": "v3.1.6",
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index f210f0591..bec0e6301 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -9,8 +9,8 @@ return array(
     '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
     '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
-    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
     '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
+    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
     '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
     '35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
     '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 94e4c70df..ccca41103 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -10,7 +10,7 @@ return array(
     'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
     'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
     'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
-    'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-queue/src', $vendorDir . '/topthink/think-template/src'),
+    'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-queue/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-filesystem/src'),
     'clagiordano\\weblibs\\configmanager\\' => array($vendorDir . '/clagiordano/weblibs-configmanager/src'),
     'app\\' => array($baseDir . '/app'),
     'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
@@ -57,6 +57,8 @@ return array(
     'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
     'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
     'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
+    'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
+    'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
     'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
     'JPush\\' => array($vendorDir . '/jpush/jpush/src/JPush'),
     'GuzzleHttp\\UriTemplate\\' => array($vendorDir . '/guzzlehttp/uri-template/src'),
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 3e0d3a872..5b1380ffd 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -10,8 +10,8 @@ class ComposerStaticInit7f3b0f886ea5f6310a43341d4e2b8ffb
         '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
         '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
-        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
         '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
+        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
         '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
         '35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
         '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
@@ -125,6 +125,11 @@ class ComposerStaticInit7f3b0f886ea5f6310a43341d4e2b8ffb
             'Monolog\\' => 8,
             'Matrix\\' => 7,
         ),
+        'L' => 
+        array (
+            'League\\MimeTypeDetection\\' => 25,
+            'League\\Flysystem\\' => 17,
+        ),
         'J' => 
         array (
             'JmesPath\\' => 9,
@@ -186,6 +191,7 @@ class ComposerStaticInit7f3b0f886ea5f6310a43341d4e2b8ffb
             2 => __DIR__ . '/..' . '/topthink/think-orm/src',
             3 => __DIR__ . '/..' . '/topthink/think-queue/src',
             4 => __DIR__ . '/..' . '/topthink/think-template/src',
+            5 => __DIR__ . '/..' . '/topthink/think-filesystem/src',
         ),
         'clagiordano\\weblibs\\configmanager\\' => 
         array (
@@ -372,6 +378,14 @@ class ComposerStaticInit7f3b0f886ea5f6310a43341d4e2b8ffb
         array (
             0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src',
         ),
+        'League\\MimeTypeDetection\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/league/mime-type-detection/src',
+        ),
+        'League\\Flysystem\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/league/flysystem/src',
+        ),
         'JmesPath\\' => 
         array (
             0 => __DIR__ . '/..' . '/mtdowling/jmespath.php/src',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 053e19f81..fc826a447 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1119,6 +1119,166 @@
             },
             "install-path": "../jpush/jpush"
         },
+        {
+            "name": "league/flysystem",
+            "version": "2.5.0",
+            "version_normalized": "2.5.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/thephpleague/flysystem.git",
+                "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8aaffb653c5777781b0f7f69a5d937baf7ab6cdb",
+                "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "league/mime-type-detection": "^1.0.0",
+                "php": "^7.2 || ^8.0"
+            },
+            "conflict": {
+                "guzzlehttp/ringphp": "<1.1.1"
+            },
+            "require-dev": {
+                "async-aws/s3": "^1.5",
+                "async-aws/simple-s3": "^1.0",
+                "aws/aws-sdk-php": "^3.132.4",
+                "composer/semver": "^3.0",
+                "ext-fileinfo": "*",
+                "ext-ftp": "*",
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "google/cloud-storage": "^1.23",
+                "phpseclib/phpseclib": "^2.0",
+                "phpstan/phpstan": "^0.12.26",
+                "phpunit/phpunit": "^8.5 || ^9.4",
+                "sabre/dav": "^4.1"
+            },
+            "time": "2022-09-17T21:02:32+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "League\\Flysystem\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frankdejonge.nl"
+                }
+            ],
+            "description": "File storage abstraction for PHP",
+            "keywords": [
+                "WebDAV",
+                "aws",
+                "cloud",
+                "file",
+                "files",
+                "filesystem",
+                "filesystems",
+                "ftp",
+                "s3",
+                "sftp",
+                "storage"
+            ],
+            "support": {
+                "issues": "https://github.com/thephpleague/flysystem/issues",
+                "source": "https://github.com/thephpleague/flysystem/tree/2.5.0"
+            },
+            "funding": [
+                {
+                    "url": "https://ecologi.com/frankdejonge",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/frankdejonge",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+                    "type": "tidelift"
+                }
+            ],
+            "install-path": "../league/flysystem"
+        },
+        {
+            "name": "league/mime-type-detection",
+            "version": "1.13.0",
+            "version_normalized": "1.13.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/thephpleague/mime-type-detection.git",
+                "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96",
+                "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-fileinfo": "*",
+                "php": "^7.4 || ^8.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "phpstan/phpstan": "^0.12.68",
+                "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
+            },
+            "time": "2023-08-05T12:09:49+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "League\\MimeTypeDetection\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frankdejonge.nl"
+                }
+            ],
+            "description": "Mime-type detection for Flysystem",
+            "support": {
+                "issues": "https://github.com/thephpleague/mime-type-detection/issues",
+                "source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/frankdejonge",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+                    "type": "tidelift"
+                }
+            ],
+            "install-path": "../league/mime-type-detection"
+        },
         {
             "name": "maennchen/zipstream-php",
             "version": "2.4.0",
@@ -4974,6 +5134,61 @@
             },
             "install-path": "../topthink/framework"
         },
+        {
+            "name": "topthink/think-filesystem",
+            "version": "v2.0.2",
+            "version_normalized": "2.0.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-filesystem.git",
+                "reference": "c08503232fcae0c3c7fefae5e6b5c841ffe09f2f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/c08503232fcae0c3c7fefae5e6b5c841ffe09f2f",
+                "reference": "c08503232fcae0c3c7fefae5e6b5c841ffe09f2f",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "league/flysystem": "^2.0",
+                "topthink/framework": "^6.1|^8.0"
+            },
+            "require-dev": {
+                "mikey179/vfsstream": "^1.6",
+                "mockery/mockery": "^1.2",
+                "phpunit/phpunit": "^8.0"
+            },
+            "time": "2023-02-08T01:23:42+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP6.1 Filesystem Package",
+            "support": {
+                "issues": "https://github.com/top-think/think-filesystem/issues",
+                "source": "https://github.com/top-think/think-filesystem/tree/v2.0.2"
+            },
+            "install-path": "../topthink/think-filesystem"
+        },
         {
             "name": "topthink/think-helper",
             "version": "v3.1.6",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 9b943b17d..6f5fb6fb5 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'topthink/think',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => '21a9cb77e8da54d360c4d1c859fce545e4c365a4',
+        'reference' => '79fc9780490166b204ecd49aaeda85e93e94cf2d',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -136,6 +136,24 @@
             'aliases' => array(),
             'dev_requirement' => false,
         ),
+        'league/flysystem' => array(
+            'pretty_version' => '2.5.0',
+            'version' => '2.5.0.0',
+            'reference' => '8aaffb653c5777781b0f7f69a5d937baf7ab6cdb',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/flysystem',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'league/mime-type-detection' => array(
+            'pretty_version' => '1.13.0',
+            'version' => '1.13.0.0',
+            'reference' => 'a6dfb1194a2946fcdc1f38219445234f65b35c96',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/mime-type-detection',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
         'maennchen/zipstream-php' => array(
             'pretty_version' => '2.4.0',
             'version' => '2.4.0.0',
@@ -658,12 +676,21 @@
         'topthink/think' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '21a9cb77e8da54d360c4d1c859fce545e4c365a4',
+            'reference' => '79fc9780490166b204ecd49aaeda85e93e94cf2d',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
             'dev_requirement' => false,
         ),
+        'topthink/think-filesystem' => array(
+            'pretty_version' => 'v2.0.2',
+            'version' => '2.0.2.0',
+            'reference' => 'c08503232fcae0c3c7fefae5e6b5c841ffe09f2f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-filesystem',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
         'topthink/think-helper' => array(
             'pretty_version' => 'v3.1.6',
             'version' => '3.1.6.0',
diff --git a/vendor/league/flysystem/INFO.md b/vendor/league/flysystem/INFO.md
new file mode 100644
index 000000000..8a44d14ec
--- /dev/null
+++ b/vendor/league/flysystem/INFO.md
@@ -0,0 +1,2 @@
+View the docs at: https://flysystem.thephpleague.com/v2/  
+Changelog at: https://github.com/thephpleague/flysystem/blob/2.x/CHANGELOG.md
diff --git a/vendor/league/flysystem/LICENSE b/vendor/league/flysystem/LICENSE
new file mode 100644
index 000000000..1f0165218
--- /dev/null
+++ b/vendor/league/flysystem/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013-2022 Frank de Jonge
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/league/flysystem/composer.json b/vendor/league/flysystem/composer.json
new file mode 100644
index 000000000..9c244f8c0
--- /dev/null
+++ b/vendor/league/flysystem/composer.json
@@ -0,0 +1,48 @@
+{
+    "name": "league/flysystem",
+    "description": "File storage abstraction for PHP",
+    "keywords": [
+        "filesystem", "filesystems", "files", "storage", "aws",
+        "s3", "ftp", "sftp", "webdav", "file", "cloud"
+    ],
+    "scripts": {
+        "phpstan": "vendor/bin/phpstan analyse -l 6 src"
+    },
+    "type": "library",
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "autoload": {
+        "psr-4": {
+            "League\\Flysystem\\": "src"
+        }
+    },
+    "require": {
+        "php": "^7.2 || ^8.0",
+        "ext-json": "*",
+        "league/mime-type-detection": "^1.0.0"
+    },
+    "require-dev": {
+        "ext-fileinfo": "*",
+        "ext-ftp": "*",
+        "phpunit/phpunit": "^8.5 || ^9.4",
+        "phpstan/phpstan": "^0.12.26",
+        "phpseclib/phpseclib": "^2.0",
+        "aws/aws-sdk-php": "^3.132.4",
+        "composer/semver": "^3.0",
+        "friendsofphp/php-cs-fixer": "^3.2",
+        "google/cloud-storage": "^1.23",
+        "async-aws/s3": "^1.5",
+        "async-aws/simple-s3": "^1.0",
+        "sabre/dav": "^4.1"
+    },
+    "conflict": {
+        "guzzlehttp/ringphp": "<1.1.1"
+    },
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Frank de Jonge",
+            "email": "info@frankdejonge.nl"
+        }
+    ]
+}
diff --git a/vendor/league/flysystem/config.subsplit-publish.json b/vendor/league/flysystem/config.subsplit-publish.json
new file mode 100644
index 000000000..b0de91ee2
--- /dev/null
+++ b/vendor/league/flysystem/config.subsplit-publish.json
@@ -0,0 +1,49 @@
+{
+    "sub-splits": [
+        {
+            "name": "ftp",
+            "directory": "src/Ftp",
+            "target": "git@github.com:thephpleague/flysystem-ftp.git"
+        },
+        {
+            "name": "sftp",
+            "directory": "src/PhpseclibV2",
+            "target": "git@github.com:thephpleague/flysystem-sftp.git"
+        },
+        {
+            "name": "sftp-v3",
+            "directory": "src/PhpseclibV3",
+            "target": "git@github.com:thephpleague/flysystem-sftp-v3.git"
+        },
+        {
+            "name": "memory",
+            "directory": "src/InMemory",
+            "target": "git@github.com:thephpleague/flysystem-memory.git"
+        },
+        {
+            "name": "ziparchive",
+            "directory": "src/ZipArchive",
+            "target": "git@github.com:thephpleague/flysystem-ziparchive.git"
+        },
+        {
+            "name": "aws-s3-v3",
+            "directory": "src/AwsS3V3",
+            "target": "git@github.com:thephpleague/flysystem-aws-s3-v3.git"
+        },
+        {
+            "name": "async-aws-s3",
+            "directory": "src/AsyncAwsS3",
+            "target": "git@github.com:thephpleague/flysystem-async-aws-s3.git"
+        },
+        {
+            "name": "google-cloud-storage",
+            "directory": "src/GoogleCloudStorage",
+            "target": "git@github.com:thephpleague/flysystem-google-cloud-storage.git"
+        },
+        {
+            "name": "adapter-test-utilities",
+            "directory": "src/AdapterTestUtilities",
+            "target": "git@github.com:thephpleague/flysystem-adapter-test-utilities.git"
+        }
+    ]
+}
diff --git a/vendor/league/flysystem/docker-compose.yml b/vendor/league/flysystem/docker-compose.yml
new file mode 100644
index 000000000..3ab6b7729
--- /dev/null
+++ b/vendor/league/flysystem/docker-compose.yml
@@ -0,0 +1,58 @@
+---
+version: "3"
+services:
+  webdav:
+    image: bytemark/webdav
+    restart: always
+    ports:
+      - "80:80"
+    environment:
+      AUTH_TYPE: Digest
+      USERNAME: alice
+      PASSWORD: secret1234
+  sftp:
+    container_name: sftp
+    restart: always
+    image: atmoz/sftp
+    volumes:
+      - ./test_files/sftp/users.conf:/etc/sftp/users.conf
+      - ./test_files/sftp/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key
+      - ./test_files/sftp/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key
+      - ./test_files/sftp/id_rsa.pub:/home/bar/.ssh/keys/id_rsa.pub
+    ports:
+      - "2222:22"
+  ftp:
+    container_name: ftp
+    restart: always
+    image: delfer/alpine-ftp-server
+    environment:
+      USERS: 'foo|pass|/home/foo/upload'
+      ADDRESS: 'localhost'
+    ports:
+      - "2121:21"
+      - "21000-21010:21000-21010"
+  ftpd:
+    container_name: ftpd
+    restart: always
+    environment:
+      PUBLICHOST: localhost
+      FTP_USER_NAME: foo
+      FTP_USER_PASS: pass
+      FTP_USER_HOME: /home/foo
+    image: stilliard/pure-ftpd
+    ports:
+      - "2122:21"
+      - "30000-30009:30000-30009"
+    command: "/run.sh -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -P localhost"
+  toxiproxy:
+    container_name: toxiproxy
+    restart: unless-stopped
+    image: ghcr.io/shopify/toxiproxy
+    command: "-host 0.0.0.0 -config /opt/toxiproxy/config.json"
+    volumes:
+      - ./test_files/toxiproxy/toxiproxy.json:/opt/toxiproxy/config.json:ro
+    ports:
+      - "8474:8474" # HTTP API
+      - "8222:8222" # SFTP
+      - "8121:8121" # FTP
+      - "8122:8122" # FTPD
diff --git a/vendor/league/flysystem/readme.md b/vendor/league/flysystem/readme.md
new file mode 100644
index 000000000..0c0b98eaf
--- /dev/null
+++ b/vendor/league/flysystem/readme.md
@@ -0,0 +1,45 @@
+# League\Flysystem
+
+[![Author](https://img.shields.io/badge/author-@frankdejonge-blue.svg)](https://twitter.com/frankdejonge)
+[![Source Code](https://img.shields.io/badge/source-thephpleague/flysystem-blue.svg)](https://github.com/thephpleague/flysystem)
+[![Latest Version](https://img.shields.io/github/tag/thephpleague/flysystem.svg)](https://github.com/thephpleague/flysystem/releases)
+[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/thephpleague/flysystem/blob/master/LICENSE)
+[![Quality Assurance](https://github.com/thephpleague/flysystem/workflows/Quality%20Assurance/badge.svg?branch=2.x)](https://github.com/thephpleague/flysystem/actions?query=workflow%3A%22Quality+Assurance%22)
+[![Total Downloads](https://img.shields.io/packagist/dt/league/flysystem.svg)](https://packagist.org/packages/league/flysystem)
+![php 7.2+](https://img.shields.io/badge/php-min%207.2-red.svg)
+
+## About Flysystem
+
+Flysystem is a file storage library for PHP. It provides one interface to
+interact with many types of filesystems. When you use Flysystem, you're
+not only protected from vendor lock-in, you'll also have a consistent experience
+for which ever storage is right for you. 
+
+## Getting Started
+
+* **[New in V2](https://flysystem.thephpleague.com/v2/docs/what-is-new/)**: What it new in Flysystem V2?
+* **[Architecture](https://flysystem.thephpleague.com/v2/docs/architecture/)**: Flysystem's internal architecture
+* **[Flysystem API](https://flysystem.thephpleague.com/v2/docs/usage/filesystem-api/)**: How to interact with your Flysystem instance
+* **[Upgrade to V2](https://flysystem.thephpleague.com/v2/docs/advanced/upgrade-to-2.0.0/)**: How to upgrade your Flysystem V1 instance to V2
+
+### Commonly-Used Adapters
+
+* **[AsyncAws S3](https://flysystem.thephpleague.com/v2/docs/adapter/async-aws-s3/)**
+* **[AWS S3](https://flysystem.thephpleague.com/v2/docs/adapter/aws-s3-v3/)**
+* **[Local](https://flysystem.thephpleague.com/v2/docs/adapter/local/)**
+* **[Memory](https://flysystem.thephpleague.com/v2/docs/adapter/in-memory/)**
+
+### Third party Adapters
+
+* **[Gitlab](https://github.com/RoyVoetman/flysystem-gitlab-storage)**
+* **[Google Drive (using regular paths)](https://github.com/masbug/flysystem-google-drive-ext)**
+
+You can always [create an adapter](https://flysystem.thephpleague.com/v2/docs/advanced/creating-an-adapter/) yourself.
+
+## Security
+
+If you discover any security related issues, please email info@frankdejonge.nl instead of using the issue tracker.
+
+## Enjoy
+
+Oh, and if you've come down this far, you might as well follow me on [twitter](https://twitter.com/frankdejonge).
diff --git a/vendor/league/flysystem/src/Config.php b/vendor/league/flysystem/src/Config.php
new file mode 100644
index 000000000..77c3b5a1d
--- /dev/null
+++ b/vendor/league/flysystem/src/Config.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use function array_merge;
+
+class Config
+{
+    public const OPTION_VISIBILITY = 'visibility';
+    public const OPTION_DIRECTORY_VISIBILITY = 'directory_visibility';
+
+    /**
+     * @var array
+     */
+    private $options;
+
+    public function __construct(array $options = [])
+    {
+        $this->options = $options;
+    }
+
+    /**
+     * @param mixed $default
+     *
+     * @return mixed
+     */
+    public function get(string $property, $default = null)
+    {
+        return $this->options[$property] ?? $default;
+    }
+
+    public function extend(array $options): Config
+    {
+        return new Config(array_merge($this->options, $options));
+    }
+
+    public function withDefaults(array $defaults): Config
+    {
+        return new Config($this->options + $defaults);
+    }
+}
diff --git a/vendor/league/flysystem/src/CorruptedPathDetected.php b/vendor/league/flysystem/src/CorruptedPathDetected.php
new file mode 100644
index 000000000..70631ccc7
--- /dev/null
+++ b/vendor/league/flysystem/src/CorruptedPathDetected.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+final class CorruptedPathDetected extends RuntimeException implements FilesystemException
+{
+    public static function forPath(string $path): CorruptedPathDetected
+    {
+        return new CorruptedPathDetected("Corrupted path detected: " . $path);
+    }
+}
diff --git a/vendor/league/flysystem/src/DirectoryAttributes.php b/vendor/league/flysystem/src/DirectoryAttributes.php
new file mode 100644
index 000000000..94e62189e
--- /dev/null
+++ b/vendor/league/flysystem/src/DirectoryAttributes.php
@@ -0,0 +1,110 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+class DirectoryAttributes implements StorageAttributes
+{
+    use ProxyArrayAccessToProperties;
+
+    /**
+     * @var string
+     */
+    private $type = StorageAttributes::TYPE_DIRECTORY;
+
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string|null
+     */
+    private $visibility;
+
+    /**
+     * @var int|null
+     */
+    private $lastModified;
+
+    /**
+     * @var array
+     */
+    private $extraMetadata;
+
+    public function __construct(string $path, ?string $visibility = null, ?int $lastModified = null, array $extraMetadata = [])
+    {
+        $this->path = $path;
+        $this->visibility = $visibility;
+        $this->lastModified = $lastModified;
+        $this->extraMetadata = $extraMetadata;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public function type(): string
+    {
+        return StorageAttributes::TYPE_DIRECTORY;
+    }
+
+    public function visibility(): ?string
+    {
+        return $this->visibility;
+    }
+
+    public function lastModified(): ?int
+    {
+        return $this->lastModified;
+    }
+
+    public function extraMetadata(): array
+    {
+        return $this->extraMetadata;
+    }
+
+    public function isFile(): bool
+    {
+        return false;
+    }
+
+    public function isDir(): bool
+    {
+        return true;
+    }
+
+    public function withPath(string $path): StorageAttributes
+    {
+        $clone = clone $this;
+        $clone->path = $path;
+
+        return $clone;
+    }
+
+    public static function fromArray(array $attributes): StorageAttributes
+    {
+        return new DirectoryAttributes(
+            $attributes[StorageAttributes::ATTRIBUTE_PATH],
+            $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? []
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function jsonSerialize(): array
+    {
+        return [
+            StorageAttributes::ATTRIBUTE_TYPE => $this->type,
+            StorageAttributes::ATTRIBUTE_PATH => $this->path,
+            StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility,
+            StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified,
+            StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata,
+        ];
+    }
+}
diff --git a/vendor/league/flysystem/src/DirectoryListing.php b/vendor/league/flysystem/src/DirectoryListing.php
new file mode 100644
index 000000000..0f429a875
--- /dev/null
+++ b/vendor/league/flysystem/src/DirectoryListing.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use ArrayIterator;
+use Generator;
+use IteratorAggregate;
+use Traversable;
+
+/**
+ * @template T
+ */
+class DirectoryListing implements IteratorAggregate
+{
+    /**
+     * @var iterable<T>
+     */
+    private $listing;
+
+    /**
+     * @param iterable<T> $listing
+     */
+    public function __construct(iterable $listing)
+    {
+        $this->listing = $listing;
+    }
+
+    public function filter(callable $filter): DirectoryListing
+    {
+        $generator = (static function (iterable $listing) use ($filter): Generator {
+            foreach ($listing as $item) {
+                if ($filter($item)) {
+                    yield $item;
+                }
+            }
+        })($this->listing);
+
+        return new DirectoryListing($generator);
+    }
+
+    public function map(callable $mapper): DirectoryListing
+    {
+        $generator = (static function (iterable $listing) use ($mapper): Generator {
+            foreach ($listing as $item) {
+                yield $mapper($item);
+            }
+        })($this->listing);
+
+        return new DirectoryListing($generator);
+    }
+
+    public function sortByPath(): DirectoryListing
+    {
+        $listing = $this->toArray();
+
+        usort($listing, function (StorageAttributes $a, StorageAttributes $b) {
+            return $a->path() <=> $b->path();
+        });
+
+        return new DirectoryListing($listing);
+    }
+
+    /**
+     * @return Traversable<T>
+     */
+    public function getIterator(): Traversable
+    {
+        return $this->listing instanceof Traversable
+            ? $this->listing
+            : new ArrayIterator($this->listing);
+    }
+
+    /**
+     * @return T[]
+     */
+    public function toArray(): array
+    {
+        return $this->listing instanceof Traversable
+            ? iterator_to_array($this->listing, false)
+            : (array) $this->listing;
+    }
+}
diff --git a/vendor/league/flysystem/src/FileAttributes.php b/vendor/league/flysystem/src/FileAttributes.php
new file mode 100644
index 000000000..2efd9c4d2
--- /dev/null
+++ b/vendor/league/flysystem/src/FileAttributes.php
@@ -0,0 +1,139 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+class FileAttributes implements StorageAttributes
+{
+    use ProxyArrayAccessToProperties;
+
+    /**
+     * @var string
+     */
+    private $type = StorageAttributes::TYPE_FILE;
+
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var int|null
+     */
+    private $fileSize;
+
+    /**
+     * @var string|null
+     */
+    private $visibility;
+
+    /**
+     * @var int|null
+     */
+    private $lastModified;
+
+    /**
+     * @var string|null
+     */
+    private $mimeType;
+
+    /**
+     * @var array
+     */
+    private $extraMetadata;
+
+    public function __construct(
+        string $path,
+        ?int $fileSize = null,
+        ?string $visibility = null,
+        ?int $lastModified = null,
+        ?string $mimeType = null,
+        array $extraMetadata = []
+    ) {
+        $this->path = $path;
+        $this->fileSize = $fileSize;
+        $this->visibility = $visibility;
+        $this->lastModified = $lastModified;
+        $this->mimeType = $mimeType;
+        $this->extraMetadata = $extraMetadata;
+    }
+
+    public function type(): string
+    {
+        return $this->type;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public function fileSize(): ?int
+    {
+        return $this->fileSize;
+    }
+
+    public function visibility(): ?string
+    {
+        return $this->visibility;
+    }
+
+    public function lastModified(): ?int
+    {
+        return $this->lastModified;
+    }
+
+    public function mimeType(): ?string
+    {
+        return $this->mimeType;
+    }
+
+    public function extraMetadata(): array
+    {
+        return $this->extraMetadata;
+    }
+
+    public function isFile(): bool
+    {
+        return true;
+    }
+
+    public function isDir(): bool
+    {
+        return false;
+    }
+
+    public function withPath(string $path): StorageAttributes
+    {
+        $clone = clone $this;
+        $clone->path = $path;
+
+        return $clone;
+    }
+
+    public static function fromArray(array $attributes): StorageAttributes
+    {
+        return new FileAttributes(
+            $attributes[StorageAttributes::ATTRIBUTE_PATH],
+            $attributes[StorageAttributes::ATTRIBUTE_FILE_SIZE] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_MIME_TYPE] ?? null,
+            $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? []
+        );
+    }
+
+    public function jsonSerialize(): array
+    {
+        return [
+            StorageAttributes::ATTRIBUTE_TYPE => self::TYPE_FILE,
+            StorageAttributes::ATTRIBUTE_PATH => $this->path,
+            StorageAttributes::ATTRIBUTE_FILE_SIZE => $this->fileSize,
+            StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility,
+            StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified,
+            StorageAttributes::ATTRIBUTE_MIME_TYPE => $this->mimeType,
+            StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata,
+        ];
+    }
+}
diff --git a/vendor/league/flysystem/src/Filesystem.php b/vendor/league/flysystem/src/Filesystem.php
new file mode 100644
index 000000000..f66574d68
--- /dev/null
+++ b/vendor/league/flysystem/src/Filesystem.php
@@ -0,0 +1,163 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+class Filesystem implements FilesystemOperator
+{
+    /**
+     * @var FilesystemAdapter
+     */
+    private $adapter;
+
+    /**
+     * @var Config
+     */
+    private $config;
+
+    /**
+     * @var PathNormalizer
+     */
+    private $pathNormalizer;
+
+    public function __construct(
+        FilesystemAdapter $adapter,
+        array $config = [],
+        PathNormalizer $pathNormalizer = null
+    ) {
+        $this->adapter = $adapter;
+        $this->config = new Config($config);
+        $this->pathNormalizer = $pathNormalizer ?: new WhitespacePathNormalizer();
+    }
+
+    public function fileExists(string $location): bool
+    {
+        return $this->adapter->fileExists($this->pathNormalizer->normalizePath($location));
+    }
+
+    public function write(string $location, string $contents, array $config = []): void
+    {
+        $this->adapter->write(
+            $this->pathNormalizer->normalizePath($location),
+            $contents,
+            $this->config->extend($config)
+        );
+    }
+
+    public function writeStream(string $location, $contents, array $config = []): void
+    {
+        /* @var resource $contents */
+        $this->assertIsResource($contents);
+        $this->rewindStream($contents);
+        $this->adapter->writeStream(
+            $this->pathNormalizer->normalizePath($location),
+            $contents,
+            $this->config->extend($config)
+        );
+    }
+
+    public function read(string $location): string
+    {
+        return $this->adapter->read($this->pathNormalizer->normalizePath($location));
+    }
+
+    public function readStream(string $location)
+    {
+        return $this->adapter->readStream($this->pathNormalizer->normalizePath($location));
+    }
+
+    public function delete(string $location): void
+    {
+        $this->adapter->delete($this->pathNormalizer->normalizePath($location));
+    }
+
+    public function deleteDirectory(string $location): void
+    {
+        $this->adapter->deleteDirectory($this->pathNormalizer->normalizePath($location));
+    }
+
+    public function createDirectory(string $location, array $config = []): void
+    {
+        $this->adapter->createDirectory(
+            $this->pathNormalizer->normalizePath($location),
+            $this->config->extend($config)
+        );
+    }
+
+    public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing
+    {
+        $path = $this->pathNormalizer->normalizePath($location);
+
+        return new DirectoryListing($this->adapter->listContents($path, $deep));
+    }
+
+    public function move(string $source, string $destination, array $config = []): void
+    {
+        $this->adapter->move(
+            $this->pathNormalizer->normalizePath($source),
+            $this->pathNormalizer->normalizePath($destination),
+            $this->config->extend($config)
+        );
+    }
+
+    public function copy(string $source, string $destination, array $config = []): void
+    {
+        $this->adapter->copy(
+            $this->pathNormalizer->normalizePath($source),
+            $this->pathNormalizer->normalizePath($destination),
+            $this->config->extend($config)
+        );
+    }
+
+    public function lastModified(string $path): int
+    {
+        return $this->adapter->lastModified($this->pathNormalizer->normalizePath($path))->lastModified();
+    }
+
+    public function fileSize(string $path): int
+    {
+        return $this->adapter->fileSize($this->pathNormalizer->normalizePath($path))->fileSize();
+    }
+
+    public function mimeType(string $path): string
+    {
+        return $this->adapter->mimeType($this->pathNormalizer->normalizePath($path))->mimeType();
+    }
+
+    public function setVisibility(string $path, string $visibility): void
+    {
+        $this->adapter->setVisibility($this->pathNormalizer->normalizePath($path), $visibility);
+    }
+
+    public function visibility(string $path): string
+    {
+        return $this->adapter->visibility($this->pathNormalizer->normalizePath($path))->visibility();
+    }
+
+    /**
+     * @param mixed $contents
+     */
+    private function assertIsResource($contents): void
+    {
+        if (is_resource($contents) === false) {
+            throw new InvalidStreamProvided(
+                "Invalid stream provided, expected stream resource, received " . gettype($contents)
+            );
+        } elseif ($type = get_resource_type($contents) !== 'stream') {
+            throw new InvalidStreamProvided(
+                "Invalid stream provided, expected stream resource, received resource of type " . $type
+            );
+        }
+    }
+
+    /**
+     * @param resource $resource
+     */
+    private function rewindStream($resource): void
+    {
+        if (ftell($resource) !== 0 && stream_get_meta_data($resource)['seekable']) {
+            rewind($resource);
+        }
+    }
+}
diff --git a/vendor/league/flysystem/src/FilesystemAdapter.php b/vendor/league/flysystem/src/FilesystemAdapter.php
new file mode 100644
index 000000000..6dcb51e40
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemAdapter.php
@@ -0,0 +1,108 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+interface FilesystemAdapter
+{
+    /**
+     * @throws FilesystemException
+     */
+    public function fileExists(string $path): bool;
+
+    /**
+     * @throws UnableToWriteFile
+     * @throws FilesystemException
+     */
+    public function write(string $path, string $contents, Config $config): void;
+
+    /**
+     * @param resource $contents
+     *
+     * @throws UnableToWriteFile
+     * @throws FilesystemException
+     */
+    public function writeStream(string $path, $contents, Config $config): void;
+
+    /**
+     * @throws UnableToReadFile
+     * @throws FilesystemException
+     */
+    public function read(string $path): string;
+
+    /**
+     * @return resource
+     *
+     * @throws UnableToReadFile
+     * @throws FilesystemException
+     */
+    public function readStream(string $path);
+
+    /**
+     * @throws UnableToDeleteFile
+     * @throws FilesystemException
+     */
+    public function delete(string $path): void;
+
+    /**
+     * @throws UnableToDeleteDirectory
+     * @throws FilesystemException
+     */
+    public function deleteDirectory(string $path): void;
+
+    /**
+     * @throws UnableToCreateDirectory
+     * @throws FilesystemException
+     */
+    public function createDirectory(string $path, Config $config): void;
+
+    /**
+     * @throws InvalidVisibilityProvided
+     * @throws FilesystemException
+     */
+    public function setVisibility(string $path, string $visibility): void;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function visibility(string $path): FileAttributes;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function mimeType(string $path): FileAttributes;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function lastModified(string $path): FileAttributes;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function fileSize(string $path): FileAttributes;
+
+    /**
+     * @return iterable<StorageAttributes>
+     *
+     * @throws FilesystemException
+     */
+    public function listContents(string $path, bool $deep): iterable;
+
+    /**
+     * @throws UnableToMoveFile
+     * @throws FilesystemException
+     */
+    public function move(string $source, string $destination, Config $config): void;
+
+    /**
+     * @throws UnableToCopyFile
+     * @throws FilesystemException
+     */
+    public function copy(string $source, string $destination, Config $config): void;
+}
diff --git a/vendor/league/flysystem/src/FilesystemException.php b/vendor/league/flysystem/src/FilesystemException.php
new file mode 100644
index 000000000..f9d60185f
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemException.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use Throwable;
+
+interface FilesystemException extends Throwable
+{
+}
diff --git a/vendor/league/flysystem/src/FilesystemOperationFailed.php b/vendor/league/flysystem/src/FilesystemOperationFailed.php
new file mode 100644
index 000000000..1c0b6df76
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemOperationFailed.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+interface FilesystemOperationFailed extends FilesystemException
+{
+    public const OPERATION_WRITE = 'WRITE';
+    public const OPERATION_UPDATE = 'UPDATE';
+    public const OPERATION_FILE_EXISTS = 'FILE_EXISTS';
+    public const OPERATION_CREATE_DIRECTORY = 'CREATE_DIRECTORY';
+    public const OPERATION_DELETE = 'DELETE';
+    public const OPERATION_DELETE_DIRECTORY = 'DELETE_DIRECTORY';
+    public const OPERATION_MOVE = 'MOVE';
+    public const OPERATION_RETRIEVE_METADATA = 'RETRIEVE_METADATA';
+    public const OPERATION_COPY = 'COPY';
+    public const OPERATION_READ = 'READ';
+    public const OPERATION_SET_VISIBILITY = 'SET_VISIBILITY';
+
+    public function operation(): string;
+}
diff --git a/vendor/league/flysystem/src/FilesystemOperator.php b/vendor/league/flysystem/src/FilesystemOperator.php
new file mode 100644
index 000000000..b7f7bd46f
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemOperator.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+interface FilesystemOperator extends FilesystemReader, FilesystemWriter
+{
+}
diff --git a/vendor/league/flysystem/src/FilesystemReader.php b/vendor/league/flysystem/src/FilesystemReader.php
new file mode 100644
index 000000000..63145d091
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemReader.php
@@ -0,0 +1,66 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+/**
+ * This interface contains everything to read from and inspect
+ * a filesystem. All methods containing are non-destructive.
+ */
+interface FilesystemReader
+{
+    public const LIST_SHALLOW = false;
+    public const LIST_DEEP = true;
+
+    /**
+     * @throws FilesystemException
+     * @throws UnableToCheckFileExistence
+     */
+    public function fileExists(string $location): bool;
+
+    /**
+     * @throws UnableToReadFile
+     * @throws FilesystemException
+     */
+    public function read(string $location): string;
+
+    /**
+     * @return resource
+     *
+     * @throws UnableToReadFile
+     * @throws FilesystemException
+     */
+    public function readStream(string $location);
+
+    /**
+     * @return DirectoryListing<StorageAttributes>
+     *
+     * @throws FilesystemException
+     */
+    public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function lastModified(string $path): int;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function fileSize(string $path): int;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function mimeType(string $path): string;
+
+    /**
+     * @throws UnableToRetrieveMetadata
+     * @throws FilesystemException
+     */
+    public function visibility(string $path): string;
+}
diff --git a/vendor/league/flysystem/src/FilesystemWriter.php b/vendor/league/flysystem/src/FilesystemWriter.php
new file mode 100644
index 000000000..a24bb0fcf
--- /dev/null
+++ b/vendor/league/flysystem/src/FilesystemWriter.php
@@ -0,0 +1,58 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+interface FilesystemWriter
+{
+    /**
+     * @throws UnableToWriteFile
+     * @throws FilesystemException
+     */
+    public function write(string $location, string $contents, array $config = []): void;
+
+    /**
+     * @param mixed $contents
+     *
+     * @throws UnableToWriteFile
+     * @throws FilesystemException
+     */
+    public function writeStream(string $location, $contents, array $config = []): void;
+
+    /**
+     * @throws UnableToSetVisibility
+     * @throws FilesystemException
+     */
+    public function setVisibility(string $path, string $visibility): void;
+
+    /**
+     * @throws UnableToDeleteFile
+     * @throws FilesystemException
+     */
+    public function delete(string $location): void;
+
+    /**
+     * @throws UnableToDeleteDirectory
+     * @throws FilesystemException
+     */
+    public function deleteDirectory(string $location): void;
+
+    /**
+     * @throws UnableToCreateDirectory
+     * @throws FilesystemException
+     */
+    public function createDirectory(string $location, array $config = []): void;
+
+    /**
+     * @throws UnableToMoveFile
+     * @throws FilesystemException
+     */
+    public function move(string $source, string $destination, array $config = []): void;
+
+    /**
+     * @throws UnableToCopyFile
+     * @throws FilesystemException
+     */
+    public function copy(string $source, string $destination, array $config = []): void;
+}
diff --git a/vendor/league/flysystem/src/InvalidStreamProvided.php b/vendor/league/flysystem/src/InvalidStreamProvided.php
new file mode 100644
index 000000000..f57b2c74a
--- /dev/null
+++ b/vendor/league/flysystem/src/InvalidStreamProvided.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidStreamProvided extends BaseInvalidArgumentException implements FilesystemException
+{
+}
diff --git a/vendor/league/flysystem/src/InvalidVisibilityProvided.php b/vendor/league/flysystem/src/InvalidVisibilityProvided.php
new file mode 100644
index 000000000..ddc1909d2
--- /dev/null
+++ b/vendor/league/flysystem/src/InvalidVisibilityProvided.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use InvalidArgumentException;
+
+use function var_export;
+
+class InvalidVisibilityProvided extends InvalidArgumentException implements FilesystemException
+{
+    public static function withVisibility(string $visibility, string $expectedMessage): InvalidVisibilityProvided
+    {
+        $provided = var_export($visibility, true);
+        $message = "Invalid visibility provided. Expected {$expectedMessage}, received {$provided}";
+
+        throw new InvalidVisibilityProvided($message);
+    }
+}
diff --git a/vendor/league/flysystem/src/Local/LocalFilesystemAdapter.php b/vendor/league/flysystem/src/Local/LocalFilesystemAdapter.php
new file mode 100644
index 000000000..83310f037
--- /dev/null
+++ b/vendor/league/flysystem/src/Local/LocalFilesystemAdapter.php
@@ -0,0 +1,419 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem\Local;
+
+use function file_put_contents;
+use const DIRECTORY_SEPARATOR;
+use const LOCK_EX;
+use DirectoryIterator;
+use FilesystemIterator;
+use Generator;
+use League\Flysystem\Config;
+use League\Flysystem\DirectoryAttributes;
+use League\Flysystem\FileAttributes;
+use League\Flysystem\FilesystemAdapter;
+use League\Flysystem\PathPrefixer;
+use League\Flysystem\SymbolicLinkEncountered;
+use League\Flysystem\UnableToCopyFile;
+use League\Flysystem\UnableToCreateDirectory;
+use League\Flysystem\UnableToDeleteDirectory;
+use League\Flysystem\UnableToDeleteFile;
+use League\Flysystem\UnableToMoveFile;
+use League\Flysystem\UnableToReadFile;
+use League\Flysystem\UnableToRetrieveMetadata;
+use League\Flysystem\UnableToSetVisibility;
+use League\Flysystem\UnableToWriteFile;
+use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
+use League\Flysystem\UnixVisibility\VisibilityConverter;
+use League\MimeTypeDetection\FinfoMimeTypeDetector;
+use League\MimeTypeDetection\MimeTypeDetector;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+use SplFileInfo;
+use function chmod;
+use function clearstatcache;
+use function dirname;
+use function error_clear_last;
+use function error_get_last;
+use function file_exists;
+use function is_dir;
+use function is_file;
+use function mkdir;
+use function rename;
+use function stream_copy_to_stream;
+
+class LocalFilesystemAdapter implements FilesystemAdapter
+{
+    /**
+     * @var int
+     */
+    public const SKIP_LINKS = 0001;
+
+    /**
+     * @var int
+     */
+    public const DISALLOW_LINKS = 0002;
+
+    /**
+     * @var PathPrefixer
+     */
+    private $prefixer;
+
+    /**
+     * @var int
+     */
+    private $writeFlags;
+
+    /**
+     * @var int
+     */
+    private $linkHandling;
+
+    /**
+     * @var VisibilityConverter
+     */
+    private $visibility;
+
+    /**
+     * @var MimeTypeDetector
+     */
+    private $mimeTypeDetector;
+
+    public function __construct(
+        string $location,
+        VisibilityConverter $visibility = null,
+        int $writeFlags = LOCK_EX,
+        int $linkHandling = self::DISALLOW_LINKS,
+        MimeTypeDetector $mimeTypeDetector = null
+    ) {
+        $this->prefixer = new PathPrefixer($location, DIRECTORY_SEPARATOR);
+        $this->writeFlags = $writeFlags;
+        $this->linkHandling = $linkHandling;
+        $this->visibility = $visibility ?: new PortableVisibilityConverter();
+        $this->ensureDirectoryExists($location, $this->visibility->defaultForDirectories());
+        $this->mimeTypeDetector = $mimeTypeDetector ?: new FinfoMimeTypeDetector();
+    }
+
+    public function write(string $path, string $contents, Config $config): void
+    {
+        $this->writeToFile($path, $contents, $config);
+    }
+
+    public function writeStream(string $path, $contents, Config $config): void
+    {
+        $this->writeToFile($path, $contents, $config);
+    }
+
+    /**
+     * @param resource|string $contents
+     */
+    private function writeToFile(string $path, $contents, Config $config): void
+    {
+        $prefixedLocation = $this->prefixer->prefixPath($path);
+        $this->ensureDirectoryExists(
+            dirname($prefixedLocation),
+            $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY))
+        );
+        error_clear_last();
+
+        if (@file_put_contents($prefixedLocation, $contents, $this->writeFlags) === false) {
+            throw UnableToWriteFile::atLocation($path, error_get_last()['message'] ?? '');
+        }
+
+        if ($visibility = $config->get(Config::OPTION_VISIBILITY)) {
+            $this->setVisibility($path, (string) $visibility);
+        }
+    }
+
+    public function delete(string $path): void
+    {
+        $location = $this->prefixer->prefixPath($path);
+
+        if ( ! file_exists($location)) {
+            return;
+        }
+
+        error_clear_last();
+
+        if ( ! @unlink($location)) {
+            throw UnableToDeleteFile::atLocation($location, error_get_last()['message'] ?? '');
+        }
+    }
+
+    public function deleteDirectory(string $prefix): void
+    {
+        $location = $this->prefixer->prefixPath($prefix);
+
+        if ( ! is_dir($location)) {
+            return;
+        }
+
+        $contents = $this->listDirectoryRecursively($location, RecursiveIteratorIterator::CHILD_FIRST);
+
+        /** @var SplFileInfo $file */
+        foreach ($contents as $file) {
+            if ( ! $this->deleteFileInfoObject($file)) {
+                throw UnableToDeleteDirectory::atLocation($prefix, "Unable to delete file at " . $file->getPathname());
+            }
+        }
+
+        unset($contents);
+
+        if ( ! @rmdir($location)) {
+            throw UnableToDeleteDirectory::atLocation($prefix, error_get_last()['message'] ?? '');
+        }
+    }
+
+    private function listDirectoryRecursively(
+        string $path,
+        int $mode = RecursiveIteratorIterator::SELF_FIRST
+    ): Generator {
+        yield from new RecursiveIteratorIterator(
+            new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
+            $mode
+        );
+    }
+
+    protected function deleteFileInfoObject(SplFileInfo $file): bool
+    {
+        switch ($file->getType()) {
+            case 'dir':
+                return @rmdir((string) $file->getRealPath());
+            case 'link':
+                return @unlink((string) $file->getPathname());
+            default:
+                return @unlink((string) $file->getRealPath());
+        }
+    }
+
+    public function listContents(string $path, bool $deep): iterable
+    {
+        $location = $this->prefixer->prefixPath($path);
+
+        if ( ! is_dir($location)) {
+            return;
+        }
+
+        /** @var SplFileInfo[] $iterator */
+        $iterator = $deep ? $this->listDirectoryRecursively($location) : $this->listDirectory($location);
+
+        foreach ($iterator as $fileInfo) {
+            if ($fileInfo->isLink()) {
+                if ($this->linkHandling & self::SKIP_LINKS) {
+                    continue;
+                }
+                throw SymbolicLinkEncountered::atLocation($fileInfo->getPathname());
+            }
+
+            $path = $this->prefixer->stripPrefix($fileInfo->getPathname());
+            $lastModified = $fileInfo->getMTime();
+            $isDirectory = $fileInfo->isDir();
+            $permissions = octdec(substr(sprintf('%o', $fileInfo->getPerms()), -4));
+            $visibility = $isDirectory ? $this->visibility->inverseForDirectory($permissions) : $this->visibility->inverseForFile($permissions);
+
+            yield $isDirectory ? new DirectoryAttributes($path, $visibility, $lastModified) : new FileAttributes(
+                str_replace('\\', '/', $path),
+                $fileInfo->getSize(),
+                $visibility,
+                $lastModified
+            );
+        }
+    }
+
+    public function move(string $source, string $destination, Config $config): void
+    {
+        $sourcePath = $this->prefixer->prefixPath($source);
+        $destinationPath = $this->prefixer->prefixPath($destination);
+        $this->ensureDirectoryExists(
+            dirname($destinationPath),
+            $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY))
+        );
+
+        if ( ! @rename($sourcePath, $destinationPath)) {
+            throw UnableToMoveFile::fromLocationTo($sourcePath, $destinationPath);
+        }
+    }
+
+    public function copy(string $source, string $destination, Config $config): void
+    {
+        $sourcePath = $this->prefixer->prefixPath($source);
+        $destinationPath = $this->prefixer->prefixPath($destination);
+        $this->ensureDirectoryExists(
+            dirname($destinationPath),
+            $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY))
+        );
+
+        if ( ! @copy($sourcePath, $destinationPath)) {
+            throw UnableToCopyFile::fromLocationTo($sourcePath, $destinationPath);
+        }
+    }
+
+    public function read(string $path): string
+    {
+        $location = $this->prefixer->prefixPath($path);
+        error_clear_last();
+        $contents = @file_get_contents($location);
+
+        if ($contents === false) {
+            throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? '');
+        }
+
+        return $contents;
+    }
+
+    public function readStream(string $path)
+    {
+        $location = $this->prefixer->prefixPath($path);
+        error_clear_last();
+        $contents = @fopen($location, 'rb');
+
+        if ($contents === false) {
+            throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? '');
+        }
+
+        return $contents;
+    }
+
+    protected function ensureDirectoryExists(string $dirname, int $visibility): void
+    {
+        if (is_dir($dirname)) {
+            return;
+        }
+
+        error_clear_last();
+
+        if ( ! @mkdir($dirname, $visibility, true)) {
+            $mkdirError = error_get_last();
+        }
+
+        clearstatcache(true, $dirname);
+
+        if ( ! is_dir($dirname)) {
+            $errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : '';
+
+            throw UnableToCreateDirectory::atLocation($dirname, $errorMessage);
+        }
+    }
+
+    public function fileExists(string $location): bool
+    {
+        $location = $this->prefixer->prefixPath($location);
+
+        return is_file($location);
+    }
+
+    public function createDirectory(string $path, Config $config): void
+    {
+        $location = $this->prefixer->prefixPath($path);
+        $visibility = $config->get(Config::OPTION_VISIBILITY, $config->get(Config::OPTION_DIRECTORY_VISIBILITY));
+        $permissions = $this->resolveDirectoryVisibility($visibility);
+
+        if (is_dir($location)) {
+            $this->setPermissions($location, $permissions);
+
+            return;
+        }
+
+        error_clear_last();
+
+        if ( ! @mkdir($location, $permissions, true)) {
+            throw UnableToCreateDirectory::atLocation($path, error_get_last()['message'] ?? '');
+        }
+    }
+
+    public function setVisibility(string $path, string $visibility): void
+    {
+        $path = $this->prefixer->prefixPath($path);
+        $visibility = is_dir($path) ? $this->visibility->forDirectory($visibility) : $this->visibility->forFile(
+            $visibility
+        );
+
+        $this->setPermissions($path, $visibility);
+    }
+
+    public function visibility(string $path): FileAttributes
+    {
+        $location = $this->prefixer->prefixPath($path);
+        clearstatcache(false, $location);
+        error_clear_last();
+        $fileperms = @fileperms($location);
+
+        if ($fileperms === false) {
+            throw UnableToRetrieveMetadata::visibility($path, error_get_last()['message'] ?? '');
+        }
+
+        $permissions = $fileperms & 0777;
+        $visibility = $this->visibility->inverseForFile($permissions);
+
+        return new FileAttributes($path, null, $visibility);
+    }
+
+    private function resolveDirectoryVisibility(?string $visibility): int
+    {
+        return $visibility === null ? $this->visibility->defaultForDirectories() : $this->visibility->forDirectory(
+            $visibility
+        );
+    }
+
+    public function mimeType(string $path): FileAttributes
+    {
+        $location = $this->prefixer->prefixPath($path);
+        error_clear_last();
+        $mimeType = $this->mimeTypeDetector->detectMimeTypeFromFile($location);
+
+        if ($mimeType === null) {
+            throw UnableToRetrieveMetadata::mimeType($path, error_get_last()['message'] ?? '');
+        }
+
+        return new FileAttributes($path, null, null, null, $mimeType);
+    }
+
+    public function lastModified(string $path): FileAttributes
+    {
+        $location = $this->prefixer->prefixPath($path);
+        error_clear_last();
+        $lastModified = @filemtime($location);
+
+        if ($lastModified === false) {
+            throw UnableToRetrieveMetadata::lastModified($path, error_get_last()['message'] ?? '');
+        }
+
+        return new FileAttributes($path, null, null, $lastModified);
+    }
+
+    public function fileSize(string $path): FileAttributes
+    {
+        $location = $this->prefixer->prefixPath($path);
+        error_clear_last();
+
+        if (is_file($location) && ($fileSize = @filesize($location)) !== false) {
+            return new FileAttributes($path, $fileSize);
+        }
+
+        throw UnableToRetrieveMetadata::fileSize($path, error_get_last()['message'] ?? '');
+    }
+
+    private function listDirectory(string $location): Generator
+    {
+        $iterator = new DirectoryIterator($location);
+
+        foreach ($iterator as $item) {
+            if ($item->isDot()) {
+                continue;
+            }
+
+            yield $item;
+        }
+    }
+
+    private function setPermissions(string $location, int $visibility): void
+    {
+        error_clear_last();
+        if ( ! @chmod($location, $visibility)) {
+            $extraMessage = error_get_last()['message'] ?? '';
+            throw UnableToSetVisibility::atLocation($this->prefixer->stripPrefix($location), $extraMessage);
+        }
+    }
+}
diff --git a/vendor/league/flysystem/src/MountManager.php b/vendor/league/flysystem/src/MountManager.php
new file mode 100644
index 000000000..b5a777353
--- /dev/null
+++ b/vendor/league/flysystem/src/MountManager.php
@@ -0,0 +1,334 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use function sprintf;
+
+class MountManager implements FilesystemOperator
+{
+    /**
+     * @var array<string, FilesystemOperator>
+     */
+    private $filesystems = [];
+
+    /**
+     * MountManager constructor.
+     *
+     * @param array<string,FilesystemOperator> $filesystems
+     */
+    public function __construct(array $filesystems = [])
+    {
+        $this->mountFilesystems($filesystems);
+    }
+
+    public function fileExists(string $location): bool
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->fileExists($path);
+        } catch (UnableToCheckFileExistence $exception) {
+            throw UnableToCheckFileExistence::forLocation($location, $exception);
+        }
+    }
+
+    public function read(string $location): string
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->read($path);
+        } catch (UnableToReadFile $exception) {
+            throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function readStream(string $location)
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->readStream($path);
+        } catch (UnableToReadFile $exception) {
+            throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path, $mountIdentifier] = $this->determineFilesystemAndPath($location);
+
+        return
+            $filesystem
+                ->listContents($path, $deep)
+                ->map(
+                    function (StorageAttributes $attributes) use ($mountIdentifier) {
+                        return $attributes->withPath(sprintf('%s://%s', $mountIdentifier, $attributes->path()));
+                    }
+                );
+    }
+
+    public function lastModified(string $location): int
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->lastModified($path);
+        } catch (UnableToRetrieveMetadata $exception) {
+            throw UnableToRetrieveMetadata::lastModified($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function fileSize(string $location): int
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->fileSize($path);
+        } catch (UnableToRetrieveMetadata $exception) {
+            throw UnableToRetrieveMetadata::fileSize($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function mimeType(string $location): string
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->mimeType($path);
+        } catch (UnableToRetrieveMetadata $exception) {
+            throw UnableToRetrieveMetadata::mimeType($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function visibility(string $location): string
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            return $filesystem->visibility($path);
+        } catch (UnableToRetrieveMetadata $exception) {
+            throw UnableToRetrieveMetadata::visibility($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function write(string $location, string $contents, array $config = []): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            $filesystem->write($path, $contents, $config);
+        } catch (UnableToWriteFile $exception) {
+            throw UnableToWriteFile::atLocation($location, $exception->reason(), $exception);
+        }
+    }
+
+    public function writeStream(string $location, $contents, array $config = []): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+        $filesystem->writeStream($path, $contents, $config);
+    }
+
+    public function setVisibility(string $path, string $visibility): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($path);
+        $filesystem->setVisibility($path, $visibility);
+    }
+
+    public function delete(string $location): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            $filesystem->delete($path);
+        } catch (UnableToDeleteFile $exception) {
+            throw UnableToDeleteFile::atLocation($location, '', $exception);
+        }
+    }
+
+    public function deleteDirectory(string $location): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            $filesystem->deleteDirectory($path);
+        } catch (UnableToDeleteDirectory $exception) {
+            throw UnableToDeleteDirectory::atLocation($location, '', $exception);
+        }
+    }
+
+    public function createDirectory(string $location, array $config = []): void
+    {
+        /** @var FilesystemOperator $filesystem */
+        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
+
+        try {
+            $filesystem->createDirectory($path, $config);
+        } catch (UnableToCreateDirectory $exception) {
+            throw UnableToCreateDirectory::dueToFailure($location, $exception);
+        }
+    }
+
+    public function move(string $source, string $destination, array $config = []): void
+    {
+        /** @var FilesystemOperator $sourceFilesystem */
+        /* @var FilesystemOperator $destinationFilesystem */
+        [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source);
+        [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination);
+
+        $sourceFilesystem === $destinationFilesystem ? $this->moveInTheSameFilesystem(
+            $sourceFilesystem,
+            $sourcePath,
+            $destinationPath,
+            $source,
+            $destination
+        ) : $this->moveAcrossFilesystems($source, $destination);
+    }
+
+    public function copy(string $source, string $destination, array $config = []): void
+    {
+        /** @var FilesystemOperator $sourceFilesystem */
+        /* @var FilesystemOperator $destinationFilesystem */
+        [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source);
+        [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination);
+
+        $sourceFilesystem === $destinationFilesystem ? $this->copyInSameFilesystem(
+            $sourceFilesystem,
+            $sourcePath,
+            $destinationPath,
+            $source,
+            $destination
+        ) : $this->copyAcrossFilesystem(
+            $config['visibility'] ?? null,
+            $sourceFilesystem,
+            $sourcePath,
+            $destinationFilesystem,
+            $destinationPath,
+            $source,
+            $destination
+        );
+    }
+
+    private function mountFilesystems(array $filesystems): void
+    {
+        foreach ($filesystems as $key => $filesystem) {
+            $this->guardAgainstInvalidMount($key, $filesystem);
+            /* @var string $key */
+            /* @var FilesystemOperator $filesystem */
+            $this->mountFilesystem($key, $filesystem);
+        }
+    }
+
+    /**
+     * @param mixed $key
+     * @param mixed $filesystem
+     */
+    private function guardAgainstInvalidMount($key, $filesystem): void
+    {
+        if ( ! is_string($key)) {
+            throw UnableToMountFilesystem::becauseTheKeyIsNotValid($key);
+        }
+
+        if ( ! $filesystem instanceof FilesystemOperator) {
+            throw UnableToMountFilesystem::becauseTheFilesystemWasNotValid($filesystem);
+        }
+    }
+
+    private function mountFilesystem(string $key, FilesystemOperator $filesystem): void
+    {
+        $this->filesystems[$key] = $filesystem;
+    }
+
+    /**
+     * @param string $path
+     *
+     * @return array{0:FilesystemOperator, 1:string}
+     */
+    private function determineFilesystemAndPath(string $path): array
+    {
+        if (strpos($path, '://') < 1) {
+            throw UnableToResolveFilesystemMount::becauseTheSeparatorIsMissing($path);
+        }
+
+        /** @var string $mountIdentifier */
+        /** @var string $mountPath */
+        [$mountIdentifier, $mountPath] = explode('://', $path, 2);
+
+        if ( ! array_key_exists($mountIdentifier, $this->filesystems)) {
+            throw UnableToResolveFilesystemMount::becauseTheMountWasNotRegistered($mountIdentifier);
+        }
+
+        return [$this->filesystems[$mountIdentifier], $mountPath, $mountIdentifier];
+    }
+
+    private function copyInSameFilesystem(
+        FilesystemOperator $sourceFilesystem,
+        string $sourcePath,
+        string $destinationPath,
+        string $source,
+        string $destination
+    ): void {
+        try {
+            $sourceFilesystem->copy($sourcePath, $destinationPath);
+        } catch (UnableToCopyFile $exception) {
+            throw UnableToCopyFile::fromLocationTo($source, $destination, $exception);
+        }
+    }
+
+    private function copyAcrossFilesystem(
+        ?string $visibility,
+        FilesystemOperator $sourceFilesystem,
+        string $sourcePath,
+        FilesystemOperator $destinationFilesystem,
+        string $destinationPath,
+        string $source,
+        string $destination
+    ): void {
+        try {
+            $visibility = $visibility ?? $sourceFilesystem->visibility($sourcePath);
+            $stream = $sourceFilesystem->readStream($sourcePath);
+            $destinationFilesystem->writeStream($destinationPath, $stream, compact('visibility'));
+        } catch (UnableToRetrieveMetadata | UnableToReadFile | UnableToWriteFile $exception) {
+            throw UnableToCopyFile::fromLocationTo($source, $destination, $exception);
+        }
+    }
+
+    private function moveInTheSameFilesystem(
+        FilesystemOperator $sourceFilesystem,
+        string $sourcePath,
+        string $destinationPath,
+        string $source,
+        string $destination
+    ): void {
+        try {
+            $sourceFilesystem->move($sourcePath, $destinationPath);
+        } catch (UnableToMoveFile $exception) {
+            throw UnableToMoveFile::fromLocationTo($source, $destination, $exception);
+        }
+    }
+
+    private function moveAcrossFilesystems(string $source, string $destination): void
+    {
+        try {
+            $this->copy($source, $destination);
+            $this->delete($source);
+        } catch (UnableToCopyFile | UnableToDeleteFile $exception) {
+            throw UnableToMoveFile::fromLocationTo($source, $destination, $exception);
+        }
+    }
+}
diff --git a/vendor/league/flysystem/src/PathNormalizer.php b/vendor/league/flysystem/src/PathNormalizer.php
new file mode 100644
index 000000000..54da201ae
--- /dev/null
+++ b/vendor/league/flysystem/src/PathNormalizer.php
@@ -0,0 +1,10 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+interface PathNormalizer
+{
+    public function normalizePath(string $path): string;
+}
diff --git a/vendor/league/flysystem/src/PathPrefixer.php b/vendor/league/flysystem/src/PathPrefixer.php
new file mode 100644
index 000000000..b675b8e5c
--- /dev/null
+++ b/vendor/league/flysystem/src/PathPrefixer.php
@@ -0,0 +1,60 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use function rtrim;
+use function strlen;
+use function substr;
+
+final class PathPrefixer
+{
+    /**
+     * @var string
+     */
+    private $prefix = '';
+
+    /**
+     * @var string
+     */
+    private $separator = '/';
+
+    public function __construct(string $prefix, string $separator = '/')
+    {
+        $this->prefix = rtrim($prefix, '\\/');
+
+        if ($this->prefix !== '' || $prefix === $separator) {
+            $this->prefix .= $separator;
+        }
+
+        $this->separator = $separator;
+    }
+
+    public function prefixPath(string $path): string
+    {
+        return $this->prefix . ltrim($path, '\\/');
+    }
+
+    public function stripPrefix(string $path): string
+    {
+        /* @var string */
+        return substr($path, strlen($this->prefix));
+    }
+
+    public function stripDirectoryPrefix(string $path): string
+    {
+        return rtrim($this->stripPrefix($path), '\\/');
+    }
+
+    public function prefixDirectoryPath(string $path): string
+    {
+        $prefixedPath = $this->prefixPath(rtrim($path, '\\/'));
+
+        if ((substr($prefixedPath, -1) === $this->separator) || $prefixedPath === '') {
+            return $prefixedPath;
+        }
+
+        return $prefixedPath . $this->separator;
+    }
+}
diff --git a/vendor/league/flysystem/src/PathTraversalDetected.php b/vendor/league/flysystem/src/PathTraversalDetected.php
new file mode 100644
index 000000000..d149997f7
--- /dev/null
+++ b/vendor/league/flysystem/src/PathTraversalDetected.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+class PathTraversalDetected extends RuntimeException implements FilesystemException
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public static function forPath(string $path): PathTraversalDetected
+    {
+        $e = new PathTraversalDetected("Path traversal detected: {$path}");
+        $e->path = $path;
+
+        return $e;
+    }
+}
diff --git a/vendor/league/flysystem/src/PortableVisibilityGuard.php b/vendor/league/flysystem/src/PortableVisibilityGuard.php
new file mode 100644
index 000000000..6e2498b42
--- /dev/null
+++ b/vendor/league/flysystem/src/PortableVisibilityGuard.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+final class PortableVisibilityGuard
+{
+    public static function guardAgainstInvalidInput(string $visibility): void
+    {
+        if ($visibility !== Visibility::PUBLIC && $visibility !== Visibility::PRIVATE) {
+            $className = Visibility::class;
+            throw InvalidVisibilityProvided::withVisibility(
+                $visibility,
+                "either {$className}::PUBLIC or {$className}::PRIVATE"
+            );
+        }
+    }
+}
diff --git a/vendor/league/flysystem/src/ProxyArrayAccessToProperties.php b/vendor/league/flysystem/src/ProxyArrayAccessToProperties.php
new file mode 100644
index 000000000..956b33000
--- /dev/null
+++ b/vendor/league/flysystem/src/ProxyArrayAccessToProperties.php
@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+/**
+ * @internal
+ */
+trait ProxyArrayAccessToProperties
+{
+    private function formatPropertyName(string $offset): string
+    {
+        return str_replace('_', '', lcfirst(ucwords($offset, '_')));
+    }
+
+    /**
+     * @param mixed $offset
+     *
+     * @return bool
+     */
+    public function offsetExists($offset): bool
+    {
+        $property = $this->formatPropertyName((string) $offset);
+
+        return isset($this->{$property});
+    }
+
+    /**
+     * @param mixed $offset
+     *
+     * @return mixed
+     */
+    #[\ReturnTypeWillChange]
+    public function offsetGet($offset)
+    {
+        $property = $this->formatPropertyName((string) $offset);
+
+        return $this->{$property};
+    }
+
+    /**
+     * @param mixed $offset
+     * @param mixed $value
+     */
+    #[\ReturnTypeWillChange]
+    public function offsetSet($offset, $value): void
+    {
+        throw new RuntimeException('Properties can not be manipulated');
+    }
+
+    /**
+     * @param mixed $offset
+     */
+    #[\ReturnTypeWillChange]
+    public function offsetUnset($offset): void
+    {
+        throw new RuntimeException('Properties can not be manipulated');
+    }
+}
diff --git a/vendor/league/flysystem/src/StorageAttributes.php b/vendor/league/flysystem/src/StorageAttributes.php
new file mode 100644
index 000000000..6be6235bd
--- /dev/null
+++ b/vendor/league/flysystem/src/StorageAttributes.php
@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use ArrayAccess;
+use JsonSerializable;
+
+interface StorageAttributes extends JsonSerializable, ArrayAccess
+{
+    public const ATTRIBUTE_PATH = 'path';
+    public const ATTRIBUTE_TYPE = 'type';
+    public const ATTRIBUTE_FILE_SIZE = 'file_size';
+    public const ATTRIBUTE_VISIBILITY = 'visibility';
+    public const ATTRIBUTE_LAST_MODIFIED = 'last_modified';
+    public const ATTRIBUTE_MIME_TYPE = 'mime_type';
+    public const ATTRIBUTE_EXTRA_METADATA = 'extra_metadata';
+
+    public const TYPE_FILE = 'file';
+    public const TYPE_DIRECTORY = 'dir';
+
+    public function path(): string;
+
+    public function type(): string;
+
+    public function visibility(): ?string;
+
+    public function lastModified(): ?int;
+
+    public static function fromArray(array $attributes): StorageAttributes;
+
+    public function isFile(): bool;
+
+    public function isDir(): bool;
+
+    public function withPath(string $path): StorageAttributes;
+
+    public function extraMetadata(): array;
+}
diff --git a/vendor/league/flysystem/src/SymbolicLinkEncountered.php b/vendor/league/flysystem/src/SymbolicLinkEncountered.php
new file mode 100644
index 000000000..8091f5904
--- /dev/null
+++ b/vendor/league/flysystem/src/SymbolicLinkEncountered.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+final class SymbolicLinkEncountered extends RuntimeException implements FilesystemException
+{
+    /**
+     * @var string
+     */
+    private $location;
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+
+    public static function atLocation(string $pathName): SymbolicLinkEncountered
+    {
+        $e = new static("Unsupported symbolic link encountered at location $pathName");
+        $e->location = $pathName;
+
+        return $e;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToCheckFileExistence.php b/vendor/league/flysystem/src/UnableToCheckFileExistence.php
new file mode 100644
index 000000000..d78e4ee89
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToCheckFileExistence.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+class UnableToCheckFileExistence extends RuntimeException implements FilesystemOperationFailed
+{
+    public static function forLocation(string $path, Throwable $exception = null): UnableToCheckFileExistence
+    {
+        return new UnableToCheckFileExistence("Unable to check file existence for: ${path}", 0, $exception);
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_FILE_EXISTS;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToCopyFile.php b/vendor/league/flysystem/src/UnableToCopyFile.php
new file mode 100644
index 000000000..2180c1e36
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToCopyFile.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToCopyFile extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $source;
+
+    /**
+     * @var string
+     */
+    private $destination;
+
+    public function source(): string
+    {
+        return $this->source;
+    }
+
+    public function destination(): string
+    {
+        return $this->destination;
+    }
+
+    public static function fromLocationTo(
+        string $sourcePath,
+        string $destinationPath,
+        Throwable $previous = null
+    ): UnableToCopyFile {
+        $e = new static("Unable to copy file from $sourcePath to $destinationPath", 0 , $previous);
+        $e->source = $sourcePath;
+        $e->destination = $destinationPath;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_COPY;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToCreateDirectory.php b/vendor/league/flysystem/src/UnableToCreateDirectory.php
new file mode 100644
index 000000000..8298f9f8c
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToCreateDirectory.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToCreateDirectory extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location;
+
+    public static function atLocation(string $dirname, string $errorMessage = ''): UnableToCreateDirectory
+    {
+        $message = "Unable to create a directory at {$dirname}. ${errorMessage}";
+        $e = new static(rtrim($message));
+        $e->location = $dirname;
+
+        return $e;
+    }
+
+    public static function dueToFailure(string $dirname, Throwable $previous): UnableToCreateDirectory
+    {
+        $message = "Unable to create a directory at {$dirname}";
+        $e = new static($message, 0, $previous);
+        $e->location = $dirname;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_CREATE_DIRECTORY;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToDeleteDirectory.php b/vendor/league/flysystem/src/UnableToDeleteDirectory.php
new file mode 100644
index 000000000..eeeab24b2
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToDeleteDirectory.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToDeleteDirectory extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location = '';
+
+    /**
+     * @var string
+     */
+    private $reason;
+
+    public static function atLocation(
+        string $location,
+        string $reason = '',
+        Throwable $previous = null
+    ): UnableToDeleteDirectory {
+        $e = new static(rtrim("Unable to delete directory located at: {$location}. {$reason}"), 0, $previous);
+        $e->location = $location;
+        $e->reason = $reason;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_DELETE_DIRECTORY;
+    }
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToDeleteFile.php b/vendor/league/flysystem/src/UnableToDeleteFile.php
new file mode 100644
index 000000000..18f7215cc
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToDeleteFile.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToDeleteFile extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location = '';
+
+    /**
+     * @var string
+     */
+    private $reason;
+
+    public static function atLocation(string $location, string $reason = '', Throwable $previous = null): UnableToDeleteFile
+    {
+        $e = new static(rtrim("Unable to delete file located at: {$location}. {$reason}"), 0, $previous);
+        $e->location = $location;
+        $e->reason = $reason;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_DELETE;
+    }
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToMountFilesystem.php b/vendor/league/flysystem/src/UnableToMountFilesystem.php
new file mode 100644
index 000000000..bd41bc98f
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToMountFilesystem.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use LogicException;
+
+class UnableToMountFilesystem extends LogicException implements FilesystemException
+{
+    /**
+     * @param mixed $key
+     */
+    public static function becauseTheKeyIsNotValid($key): UnableToMountFilesystem
+    {
+        return new UnableToMountFilesystem(
+            'Unable to mount filesystem, key was invalid. String expected, received: ' . gettype($key)
+        );
+    }
+
+    /**
+     * @param mixed $filesystem
+     */
+    public static function becauseTheFilesystemWasNotValid($filesystem): UnableToMountFilesystem
+    {
+        $received = is_object($filesystem) ? get_class($filesystem) : gettype($filesystem);
+
+        return new UnableToMountFilesystem(
+            'Unable to mount filesystem, filesystem was invalid. Instance of ' . FilesystemOperator::class . ' expected, received: ' . $received
+        );
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToMoveFile.php b/vendor/league/flysystem/src/UnableToMoveFile.php
new file mode 100644
index 000000000..4360d1765
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToMoveFile.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToMoveFile extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $source;
+
+    /**
+     * @var string
+     */
+    private $destination;
+
+    public function source(): string
+    {
+        return $this->source;
+    }
+
+    public function destination(): string
+    {
+        return $this->destination;
+    }
+
+    public static function fromLocationTo(
+        string $sourcePath,
+        string $destinationPath,
+        Throwable $previous = null
+    ): UnableToMoveFile {
+        $e = new static("Unable to move file from $sourcePath to $destinationPath", 0, $previous);
+        $e->source = $sourcePath;
+        $e->destination = $destinationPath;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_MOVE;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToReadFile.php b/vendor/league/flysystem/src/UnableToReadFile.php
new file mode 100644
index 000000000..766b56309
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToReadFile.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToReadFile extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location = '';
+
+    /**
+     * @var string
+     */
+    private $reason = '';
+
+    public static function fromLocation(string $location, string $reason = '', Throwable $previous = null): UnableToReadFile
+    {
+        $e = new static(rtrim("Unable to read file from location: {$location}. {$reason}"), 0, $previous);
+        $e->location = $location;
+        $e->reason = $reason;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_READ;
+    }
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php b/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php
new file mode 100644
index 000000000..91a9ee3e3
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+class UnableToResolveFilesystemMount extends RuntimeException implements FilesystemException
+{
+    public static function becauseTheSeparatorIsMissing(string $path): UnableToResolveFilesystemMount
+    {
+        return new UnableToResolveFilesystemMount("Unable to resolve the filesystem mount because the path ($path) is missing a separator (://).");
+    }
+
+    public static function becauseTheMountWasNotRegistered(string $mountIdentifier): UnableToResolveFilesystemMount
+    {
+        return new UnableToResolveFilesystemMount("Unable to resolve the filesystem mount because the mount ($mountIdentifier) was not registered.");
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToRetrieveMetadata.php b/vendor/league/flysystem/src/UnableToRetrieveMetadata.php
new file mode 100644
index 000000000..11cec7f99
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToRetrieveMetadata.php
@@ -0,0 +1,76 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToRetrieveMetadata extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location;
+
+    /**
+     * @var string
+     */
+    private $metadataType;
+
+    /**
+     * @var string
+     */
+    private $reason;
+
+    public static function lastModified(string $location, string $reason = '', Throwable $previous = null): self
+    {
+        return static::create($location, FileAttributes::ATTRIBUTE_LAST_MODIFIED, $reason, $previous);
+    }
+
+    public static function visibility(string $location, string $reason = '', Throwable $previous = null): self
+    {
+        return static::create($location, FileAttributes::ATTRIBUTE_VISIBILITY, $reason, $previous);
+    }
+
+    public static function fileSize(string $location, string $reason = '', Throwable $previous = null): self
+    {
+        return static::create($location, FileAttributes::ATTRIBUTE_FILE_SIZE, $reason, $previous);
+    }
+
+    public static function mimeType(string $location, string $reason = '', Throwable $previous = null): self
+    {
+        return static::create($location, FileAttributes::ATTRIBUTE_MIME_TYPE, $reason, $previous);
+    }
+
+    public static function create(string $location, string $type, string $reason = '', Throwable $previous = null): self
+    {
+        $e = new static("Unable to retrieve the $type for file at location: $location. {$reason}", 0, $previous);
+        $e->reason = $reason;
+        $e->location = $location;
+        $e->metadataType = $type;
+
+        return $e;
+    }
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+
+    public function metadataType(): string
+    {
+        return $this->metadataType;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_RETRIEVE_METADATA;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToSetVisibility.php b/vendor/league/flysystem/src/UnableToSetVisibility.php
new file mode 100644
index 000000000..5862d0e0c
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToSetVisibility.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+use Throwable;
+
+use function rtrim;
+
+final class UnableToSetVisibility extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location;
+
+    /**
+     * @var string
+     */
+    private $reason;
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public static function atLocation(string $filename, string $extraMessage = '', Throwable $previous = null): self
+    {
+        $message = "Unable to set visibility for file {$filename}. $extraMessage";
+        $e = new static(rtrim($message), 0, $previous);
+        $e->reason = $extraMessage;
+        $e->location = $filename;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_SET_VISIBILITY;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnableToWriteFile.php b/vendor/league/flysystem/src/UnableToWriteFile.php
new file mode 100644
index 000000000..5de786658
--- /dev/null
+++ b/vendor/league/flysystem/src/UnableToWriteFile.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use Throwable;
+
+final class UnableToWriteFile extends RuntimeException implements FilesystemOperationFailed
+{
+    /**
+     * @var string
+     */
+    private $location = '';
+
+    /**
+     * @var string
+     */
+    private $reason;
+
+    public static function atLocation(string $location, string $reason = '', Throwable $previous = null): UnableToWriteFile
+    {
+        $e = new static(rtrim("Unable to write file at location: {$location}. {$reason}"), 0, $previous);
+        $e->location = $location;
+        $e->reason = $reason;
+
+        return $e;
+    }
+
+    public function operation(): string
+    {
+        return FilesystemOperationFailed::OPERATION_WRITE;
+    }
+
+    public function reason(): string
+    {
+        return $this->reason;
+    }
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+}
diff --git a/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php b/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php
new file mode 100644
index 000000000..5cc1eb232
--- /dev/null
+++ b/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php
@@ -0,0 +1,109 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem\UnixVisibility;
+
+use League\Flysystem\PortableVisibilityGuard;
+use League\Flysystem\Visibility;
+
+class PortableVisibilityConverter implements VisibilityConverter
+{
+    /**
+     * @var int
+     */
+    private $filePublic;
+
+    /**
+     * @var int
+     */
+    private $filePrivate;
+
+    /**
+     * @var int
+     */
+    private $directoryPublic;
+
+    /**
+     * @var int
+     */
+    private $directoryPrivate;
+
+    /**
+     * @var string
+     */
+    private $defaultForDirectories;
+
+    public function __construct(
+        int $filePublic = 0644,
+        int $filePrivate = 0600,
+        int $directoryPublic = 0755,
+        int $directoryPrivate = 0700,
+        string $defaultForDirectories = Visibility::PRIVATE
+    ) {
+        $this->filePublic = $filePublic;
+        $this->filePrivate = $filePrivate;
+        $this->directoryPublic = $directoryPublic;
+        $this->directoryPrivate = $directoryPrivate;
+        $this->defaultForDirectories = $defaultForDirectories;
+    }
+
+    public function forFile(string $visibility): int
+    {
+        PortableVisibilityGuard::guardAgainstInvalidInput($visibility);
+
+        return $visibility === Visibility::PUBLIC
+            ? $this->filePublic
+            : $this->filePrivate;
+    }
+
+    public function forDirectory(string $visibility): int
+    {
+        PortableVisibilityGuard::guardAgainstInvalidInput($visibility);
+
+        return $visibility === Visibility::PUBLIC
+            ? $this->directoryPublic
+            : $this->directoryPrivate;
+    }
+
+    public function inverseForFile(int $visibility): string
+    {
+        if ($visibility === $this->filePublic) {
+            return Visibility::PUBLIC;
+        } elseif ($visibility === $this->filePrivate) {
+            return Visibility::PRIVATE;
+        }
+
+        return Visibility::PUBLIC; // default
+    }
+
+    public function inverseForDirectory(int $visibility): string
+    {
+        if ($visibility === $this->directoryPublic) {
+            return Visibility::PUBLIC;
+        } elseif ($visibility === $this->directoryPrivate) {
+            return Visibility::PRIVATE;
+        }
+
+        return Visibility::PUBLIC; // default
+    }
+
+    public function defaultForDirectories(): int
+    {
+        return $this->defaultForDirectories === Visibility::PUBLIC ? $this->directoryPublic : $this->directoryPrivate;
+    }
+
+    /**
+     * @param array<mixed>  $permissionMap
+     */
+    public static function fromArray(array $permissionMap, string $defaultForDirectories = Visibility::PRIVATE): PortableVisibilityConverter
+    {
+        return new PortableVisibilityConverter(
+            $permissionMap['file']['public'] ?? 0644,
+            $permissionMap['file']['private'] ?? 0600,
+            $permissionMap['dir']['public'] ?? 0755,
+            $permissionMap['dir']['private'] ?? 0700,
+            $defaultForDirectories
+        );
+    }
+}
diff --git a/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php b/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php
new file mode 100644
index 000000000..64af86a07
--- /dev/null
+++ b/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem\UnixVisibility;
+
+interface VisibilityConverter
+{
+    public function forFile(string $visibility): int;
+    public function forDirectory(string $visibility): int;
+    public function inverseForFile(int $visibility): string;
+    public function inverseForDirectory(int $visibility): string;
+    public function defaultForDirectories(): int;
+}
diff --git a/vendor/league/flysystem/src/UnreadableFileEncountered.php b/vendor/league/flysystem/src/UnreadableFileEncountered.php
new file mode 100644
index 000000000..e31952d48
--- /dev/null
+++ b/vendor/league/flysystem/src/UnreadableFileEncountered.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+final class UnreadableFileEncountered extends RuntimeException implements FilesystemException
+{
+    /**
+     * @var string
+     */
+    private $location;
+
+    public function location(): string
+    {
+        return $this->location;
+    }
+
+    public static function atLocation(string $location): UnreadableFileEncountered
+    {
+        $e = new static("Unreadable file encountered at location {$location}.");
+        $e->location = $location;
+
+        return $e;
+    }
+}
diff --git a/vendor/league/flysystem/src/Visibility.php b/vendor/league/flysystem/src/Visibility.php
new file mode 100644
index 000000000..071ca0000
--- /dev/null
+++ b/vendor/league/flysystem/src/Visibility.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+final class Visibility
+{
+    public const PUBLIC = 'public';
+    public const PRIVATE = 'private';
+}
diff --git a/vendor/league/flysystem/src/WhitespacePathNormalizer.php b/vendor/league/flysystem/src/WhitespacePathNormalizer.php
new file mode 100644
index 000000000..135b22a48
--- /dev/null
+++ b/vendor/league/flysystem/src/WhitespacePathNormalizer.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\Flysystem;
+
+class WhitespacePathNormalizer implements PathNormalizer
+{
+    public function normalizePath(string $path): string
+    {
+        $path = str_replace('\\', '/', $path);
+        $this->rejectFunkyWhiteSpace($path);
+
+        return $this->normalizeRelativePath($path);
+    }
+
+    private function rejectFunkyWhiteSpace(string $path): void
+    {
+        if (preg_match('#\p{C}+#u', $path)) {
+            throw CorruptedPathDetected::forPath($path);
+        }
+    }
+
+    private function normalizeRelativePath(string $path): string
+    {
+        $parts = [];
+
+        foreach (explode('/', $path) as $part) {
+            switch ($part) {
+                case '':
+                case '.':
+                    break;
+
+                case '..':
+                    if (empty($parts)) {
+                        throw PathTraversalDetected::forPath($path);
+                    }
+                    array_pop($parts);
+                    break;
+
+                default:
+                    $parts[] = $part;
+                    break;
+            }
+        }
+
+        return implode('/', $parts);
+    }
+}
diff --git a/vendor/league/mime-type-detection/CHANGELOG.md b/vendor/league/mime-type-detection/CHANGELOG.md
new file mode 100644
index 000000000..653ca5181
--- /dev/null
+++ b/vendor/league/mime-type-detection/CHANGELOG.md
@@ -0,0 +1,49 @@
+# Changelog
+
+## 1.13.0 - 2022-08-05
+
+### Added
+
+- A reverse lookup mechanism to fetch one or all extensions for a given mimetype
+
+## 1.12.0 - 2022-08-03
+
+### Updated
+
+- Updated lookup
+
+## 1.11.0 - 2022-04-17
+
+### Updated
+
+- Updated lookup
+
+## 1.10.0 - 2022-04-11
+
+### Fixed
+
+- Added Flysystem v1 inconclusive mime-types and made it configurable as a constructor parameter.
+
+## 1.9.0 - 2021-11-21
+
+### Updated
+
+- Updated lookup
+
+## 1.8.0 - 2021-09-25
+
+### Added
+
+- Added the decorator `OverridingExtensionToMimeTypeMap` which allows you to override values.
+
+## 1.7.0 - 2021-01-18
+
+### Added
+
+- Added a `bufferSampleSize` parameter to the `FinfoMimeTypeDetector` class that allows you to send a reduced content sample which costs less memory.
+
+## 1.6.0 - 2021-01-18
+
+### Changes
+
+- Updated generated mime-type map
diff --git a/vendor/league/mime-type-detection/LICENSE b/vendor/league/mime-type-detection/LICENSE
new file mode 100644
index 000000000..39d50b5e7
--- /dev/null
+++ b/vendor/league/mime-type-detection/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013-2023 Frank de Jonge
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/league/mime-type-detection/composer.json b/vendor/league/mime-type-detection/composer.json
new file mode 100644
index 000000000..cd75beea7
--- /dev/null
+++ b/vendor/league/mime-type-detection/composer.json
@@ -0,0 +1,34 @@
+{
+    "name": "league/mime-type-detection",
+    "description": "Mime-type detection for Flysystem",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Frank de Jonge",
+            "email": "info@frankdejonge.nl"
+        }
+    ],
+    "scripts": {
+        "test": "vendor/bin/phpunit",
+        "phpstan": "vendor/bin/phpstan analyse -l 6 src"
+    },
+    "require": {
+        "php": "^7.4 || ^8.0",
+        "ext-fileinfo": "*"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0",
+        "phpstan/phpstan": "^0.12.68",
+        "friendsofphp/php-cs-fixer": "^3.2"
+    },
+    "autoload": {
+        "psr-4": {
+            "League\\MimeTypeDetection\\": "src"
+        }
+    },
+    "config": {
+        "platform": {
+            "php": "7.4.0"
+        }
+    }
+}
diff --git a/vendor/league/mime-type-detection/src/EmptyExtensionToMimeTypeMap.php b/vendor/league/mime-type-detection/src/EmptyExtensionToMimeTypeMap.php
new file mode 100644
index 000000000..fc0424161
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/EmptyExtensionToMimeTypeMap.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+class EmptyExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
+{
+    public function lookupMimeType(string $extension): ?string
+    {
+        return null;
+    }
+}
diff --git a/vendor/league/mime-type-detection/src/ExtensionLookup.php b/vendor/league/mime-type-detection/src/ExtensionLookup.php
new file mode 100644
index 000000000..14b89df5d
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/ExtensionLookup.php
@@ -0,0 +1,14 @@
+<?php
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+interface ExtensionLookup
+{
+    public function lookupExtension(string $mimetype): ?string;
+
+    /**
+     * @return string[]
+     */
+    public function lookupAllExtensions(string $mimetype): array;
+}
diff --git a/vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php b/vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php
new file mode 100644
index 000000000..cd3446202
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+use const PATHINFO_EXTENSION;
+
+class ExtensionMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
+{
+    /**
+     * @var ExtensionToMimeTypeMap
+     */
+    private $extensions;
+
+    public function __construct(ExtensionToMimeTypeMap $extensions = null)
+    {
+        $this->extensions = $extensions ?: new GeneratedExtensionToMimeTypeMap();
+    }
+
+    public function detectMimeType(string $path, $contents): ?string
+    {
+        return $this->detectMimeTypeFromPath($path);
+    }
+
+    public function detectMimeTypeFromPath(string $path): ?string
+    {
+        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
+
+        return $this->extensions->lookupMimeType($extension);
+    }
+
+    public function detectMimeTypeFromFile(string $path): ?string
+    {
+        return $this->detectMimeTypeFromPath($path);
+    }
+
+    public function detectMimeTypeFromBuffer(string $contents): ?string
+    {
+        return null;
+    }
+
+    public function lookupExtension(string $mimetype): ?string
+    {
+        return $this->extensions instanceof ExtensionLookup
+            ? $this->extensions->lookupExtension($mimetype)
+            : null;
+    }
+
+    public function lookupAllExtensions(string $mimetype): array
+    {
+        return $this->extensions instanceof ExtensionLookup
+            ? $this->extensions->lookupAllExtensions($mimetype)
+            : [];
+    }
+}
diff --git a/vendor/league/mime-type-detection/src/ExtensionToMimeTypeMap.php b/vendor/league/mime-type-detection/src/ExtensionToMimeTypeMap.php
new file mode 100644
index 000000000..1dad7bc1a
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/ExtensionToMimeTypeMap.php
@@ -0,0 +1,10 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+interface ExtensionToMimeTypeMap
+{
+    public function lookupMimeType(string $extension): ?string;
+}
diff --git a/vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php b/vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php
new file mode 100644
index 000000000..8084f9247
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+use const FILEINFO_MIME_TYPE;
+
+use const PATHINFO_EXTENSION;
+use finfo;
+
+class FinfoMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
+{
+    private const INCONCLUSIVE_MIME_TYPES = [
+        'application/x-empty',
+        'text/plain',
+        'text/x-asm',
+        'application/octet-stream',
+        'inode/x-empty',
+    ];
+
+    /**
+     * @var finfo
+     */
+    private $finfo;
+
+    /**
+     * @var ExtensionToMimeTypeMap
+     */
+    private $extensionMap;
+
+    /**
+     * @var int|null
+     */
+    private $bufferSampleSize;
+
+    /**
+     * @var array<string>
+     */
+    private $inconclusiveMimetypes;
+
+    public function __construct(
+        string $magicFile = '',
+        ExtensionToMimeTypeMap $extensionMap = null,
+        ?int $bufferSampleSize = null,
+        array $inconclusiveMimetypes = self::INCONCLUSIVE_MIME_TYPES
+    ) {
+        $this->finfo = new finfo(FILEINFO_MIME_TYPE, $magicFile);
+        $this->extensionMap = $extensionMap ?: new GeneratedExtensionToMimeTypeMap();
+        $this->bufferSampleSize = $bufferSampleSize;
+        $this->inconclusiveMimetypes = $inconclusiveMimetypes;
+    }
+
+    public function detectMimeType(string $path, $contents): ?string
+    {
+        $mimeType = is_string($contents)
+            ? (@$this->finfo->buffer($this->takeSample($contents)) ?: null)
+            : null;
+
+        if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) {
+            return $mimeType;
+        }
+
+        return $this->detectMimeTypeFromPath($path);
+    }
+
+    public function detectMimeTypeFromPath(string $path): ?string
+    {
+        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
+
+        return $this->extensionMap->lookupMimeType($extension);
+    }
+
+    public function detectMimeTypeFromFile(string $path): ?string
+    {
+        return @$this->finfo->file($path) ?: null;
+    }
+
+    public function detectMimeTypeFromBuffer(string $contents): ?string
+    {
+        return @$this->finfo->buffer($this->takeSample($contents)) ?: null;
+    }
+
+    private function takeSample(string $contents): string
+    {
+        if ($this->bufferSampleSize === null) {
+            return $contents;
+        }
+
+        return (string) substr($contents, 0, $this->bufferSampleSize);
+    }
+
+    public function lookupExtension(string $mimetype): ?string
+    {
+        return $this->extensionMap instanceof ExtensionLookup
+            ? $this->extensionMap->lookupExtension($mimetype)
+            : null;
+    }
+
+    public function lookupAllExtensions(string $mimetype): array
+    {
+        return $this->extensionMap instanceof ExtensionLookup
+            ? $this->extensionMap->lookupAllExtensions($mimetype)
+            : [];
+    }
+}
diff --git a/vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php b/vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php
new file mode 100644
index 000000000..72f515fbc
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php
@@ -0,0 +1,2291 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap, ExtensionLookup
+{
+    /**
+     * @var array<string, string>
+     *
+     * @internal
+     */
+    public const MIME_TYPES_FOR_EXTENSIONS = [
+        '1km' => 'application/vnd.1000minds.decision-model+xml',
+        '3dml' => 'text/vnd.in3d.3dml',
+        '3ds' => 'image/x-3ds',
+        '3g2' => 'video/3gpp2',
+        '3gp' => 'video/3gp',
+        '3gpp' => 'video/3gpp',
+        '3mf' => 'model/3mf',
+        '7z' => 'application/x-7z-compressed',
+        '7zip' => 'application/x-7z-compressed',
+        '123' => 'application/vnd.lotus-1-2-3',
+        'aab' => 'application/x-authorware-bin',
+        'aac' => 'audio/acc',
+        'aam' => 'application/x-authorware-map',
+        'aas' => 'application/x-authorware-seg',
+        'abw' => 'application/x-abiword',
+        'ac' => 'application/vnd.nokia.n-gage.ac+xml',
+        'ac3' => 'audio/ac3',
+        'acc' => 'application/vnd.americandynamics.acc',
+        'ace' => 'application/x-ace-compressed',
+        'acu' => 'application/vnd.acucobol',
+        'acutc' => 'application/vnd.acucorp',
+        'adp' => 'audio/adpcm',
+        'adts' => 'audio/aac',
+        'aep' => 'application/vnd.audiograph',
+        'afm' => 'application/x-font-type1',
+        'afp' => 'application/vnd.ibm.modcap',
+        'age' => 'application/vnd.age',
+        'ahead' => 'application/vnd.ahead.space',
+        'ai' => 'application/pdf',
+        'aif' => 'audio/x-aiff',
+        'aifc' => 'audio/x-aiff',
+        'aiff' => 'audio/x-aiff',
+        'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+        'ait' => 'application/vnd.dvb.ait',
+        'ami' => 'application/vnd.amiga.ami',
+        'aml' => 'application/automationml-aml+xml',
+        'amlx' => 'application/automationml-amlx+zip',
+        'amr' => 'audio/amr',
+        'apk' => 'application/vnd.android.package-archive',
+        'apng' => 'image/apng',
+        'appcache' => 'text/cache-manifest',
+        'appinstaller' => 'application/appinstaller',
+        'application' => 'application/x-ms-application',
+        'appx' => 'application/appx',
+        'appxbundle' => 'application/appxbundle',
+        'apr' => 'application/vnd.lotus-approach',
+        'arc' => 'application/x-freearc',
+        'arj' => 'application/x-arj',
+        'asc' => 'application/pgp-signature',
+        'asf' => 'video/x-ms-asf',
+        'asm' => 'text/x-asm',
+        'aso' => 'application/vnd.accpac.simply.aso',
+        'asx' => 'video/x-ms-asf',
+        'atc' => 'application/vnd.acucorp',
+        'atom' => 'application/atom+xml',
+        'atomcat' => 'application/atomcat+xml',
+        'atomdeleted' => 'application/atomdeleted+xml',
+        'atomsvc' => 'application/atomsvc+xml',
+        'atx' => 'application/vnd.antix.game-component',
+        'au' => 'audio/x-au',
+        'avci' => 'image/avci',
+        'avcs' => 'image/avcs',
+        'avi' => 'video/x-msvideo',
+        'avif' => 'image/avif',
+        'aw' => 'application/applixware',
+        'azf' => 'application/vnd.airzip.filesecure.azf',
+        'azs' => 'application/vnd.airzip.filesecure.azs',
+        'azv' => 'image/vnd.airzip.accelerator.azv',
+        'azw' => 'application/vnd.amazon.ebook',
+        'b16' => 'image/vnd.pco.b16',
+        'bat' => 'application/x-msdownload',
+        'bcpio' => 'application/x-bcpio',
+        'bdf' => 'application/x-font-bdf',
+        'bdm' => 'application/vnd.syncml.dm+wbxml',
+        'bdoc' => 'application/x-bdoc',
+        'bed' => 'application/vnd.realvnc.bed',
+        'bh2' => 'application/vnd.fujitsu.oasysprs',
+        'bin' => 'application/octet-stream',
+        'blb' => 'application/x-blorb',
+        'blorb' => 'application/x-blorb',
+        'bmi' => 'application/vnd.bmi',
+        'bmml' => 'application/vnd.balsamiq.bmml+xml',
+        'bmp' => 'image/bmp',
+        'book' => 'application/vnd.framemaker',
+        'box' => 'application/vnd.previewsystems.box',
+        'boz' => 'application/x-bzip2',
+        'bpk' => 'application/octet-stream',
+        'bpmn' => 'application/octet-stream',
+        'bsp' => 'model/vnd.valve.source.compiled-map',
+        'btf' => 'image/prs.btif',
+        'btif' => 'image/prs.btif',
+        'buffer' => 'application/octet-stream',
+        'bz' => 'application/x-bzip',
+        'bz2' => 'application/x-bzip2',
+        'c' => 'text/x-c',
+        'c4d' => 'application/vnd.clonk.c4group',
+        'c4f' => 'application/vnd.clonk.c4group',
+        'c4g' => 'application/vnd.clonk.c4group',
+        'c4p' => 'application/vnd.clonk.c4group',
+        'c4u' => 'application/vnd.clonk.c4group',
+        'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+        'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+        'cab' => 'application/vnd.ms-cab-compressed',
+        'caf' => 'audio/x-caf',
+        'cap' => 'application/vnd.tcpdump.pcap',
+        'car' => 'application/vnd.curl.car',
+        'cat' => 'application/vnd.ms-pki.seccat',
+        'cb7' => 'application/x-cbr',
+        'cba' => 'application/x-cbr',
+        'cbr' => 'application/x-cbr',
+        'cbt' => 'application/x-cbr',
+        'cbz' => 'application/x-cbr',
+        'cc' => 'text/x-c',
+        'cco' => 'application/x-cocoa',
+        'cct' => 'application/x-director',
+        'ccxml' => 'application/ccxml+xml',
+        'cdbcmsg' => 'application/vnd.contact.cmsg',
+        'cdf' => 'application/x-netcdf',
+        'cdfx' => 'application/cdfx+xml',
+        'cdkey' => 'application/vnd.mediastation.cdkey',
+        'cdmia' => 'application/cdmi-capability',
+        'cdmic' => 'application/cdmi-container',
+        'cdmid' => 'application/cdmi-domain',
+        'cdmio' => 'application/cdmi-object',
+        'cdmiq' => 'application/cdmi-queue',
+        'cdr' => 'application/cdr',
+        'cdx' => 'chemical/x-cdx',
+        'cdxml' => 'application/vnd.chemdraw+xml',
+        'cdy' => 'application/vnd.cinderella',
+        'cer' => 'application/pkix-cert',
+        'cfs' => 'application/x-cfs-compressed',
+        'cgm' => 'image/cgm',
+        'chat' => 'application/x-chat',
+        'chm' => 'application/vnd.ms-htmlhelp',
+        'chrt' => 'application/vnd.kde.kchart',
+        'cif' => 'chemical/x-cif',
+        'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+        'cil' => 'application/vnd.ms-artgalry',
+        'cjs' => 'application/node',
+        'cla' => 'application/vnd.claymore',
+        'class' => 'application/octet-stream',
+        'cld' => 'model/vnd.cld',
+        'clkk' => 'application/vnd.crick.clicker.keyboard',
+        'clkp' => 'application/vnd.crick.clicker.palette',
+        'clkt' => 'application/vnd.crick.clicker.template',
+        'clkw' => 'application/vnd.crick.clicker.wordbank',
+        'clkx' => 'application/vnd.crick.clicker',
+        'clp' => 'application/x-msclip',
+        'cmc' => 'application/vnd.cosmocaller',
+        'cmdf' => 'chemical/x-cmdf',
+        'cml' => 'chemical/x-cml',
+        'cmp' => 'application/vnd.yellowriver-custom-menu',
+        'cmx' => 'image/x-cmx',
+        'cod' => 'application/vnd.rim.cod',
+        'coffee' => 'text/coffeescript',
+        'com' => 'application/x-msdownload',
+        'conf' => 'text/plain',
+        'cpio' => 'application/x-cpio',
+        'cpl' => 'application/cpl+xml',
+        'cpp' => 'text/x-c',
+        'cpt' => 'application/mac-compactpro',
+        'crd' => 'application/x-mscardfile',
+        'crl' => 'application/pkix-crl',
+        'crt' => 'application/x-x509-ca-cert',
+        'crx' => 'application/x-chrome-extension',
+        'cryptonote' => 'application/vnd.rig.cryptonote',
+        'csh' => 'application/x-csh',
+        'csl' => 'application/vnd.citationstyles.style+xml',
+        'csml' => 'chemical/x-csml',
+        'csp' => 'application/vnd.commonspace',
+        'csr' => 'application/octet-stream',
+        'css' => 'text/css',
+        'cst' => 'application/x-director',
+        'csv' => 'text/csv',
+        'cu' => 'application/cu-seeme',
+        'curl' => 'text/vnd.curl',
+        'cwl' => 'application/cwl',
+        'cww' => 'application/prs.cww',
+        'cxt' => 'application/x-director',
+        'cxx' => 'text/x-c',
+        'dae' => 'model/vnd.collada+xml',
+        'daf' => 'application/vnd.mobius.daf',
+        'dart' => 'application/vnd.dart',
+        'dataless' => 'application/vnd.fdsn.seed',
+        'davmount' => 'application/davmount+xml',
+        'dbf' => 'application/vnd.dbf',
+        'dbk' => 'application/docbook+xml',
+        'dcr' => 'application/x-director',
+        'dcurl' => 'text/vnd.curl.dcurl',
+        'dd2' => 'application/vnd.oma.dd2+xml',
+        'ddd' => 'application/vnd.fujixerox.ddd',
+        'ddf' => 'application/vnd.syncml.dmddf+xml',
+        'dds' => 'image/vnd.ms-dds',
+        'deb' => 'application/x-debian-package',
+        'def' => 'text/plain',
+        'deploy' => 'application/octet-stream',
+        'der' => 'application/x-x509-ca-cert',
+        'dfac' => 'application/vnd.dreamfactory',
+        'dgc' => 'application/x-dgc-compressed',
+        'dib' => 'image/bmp',
+        'dic' => 'text/x-c',
+        'dir' => 'application/x-director',
+        'dis' => 'application/vnd.mobius.dis',
+        'disposition-notification' => 'message/disposition-notification',
+        'dist' => 'application/octet-stream',
+        'distz' => 'application/octet-stream',
+        'djv' => 'image/vnd.djvu',
+        'djvu' => 'image/vnd.djvu',
+        'dll' => 'application/octet-stream',
+        'dmg' => 'application/x-apple-diskimage',
+        'dmn' => 'application/octet-stream',
+        'dmp' => 'application/vnd.tcpdump.pcap',
+        'dms' => 'application/octet-stream',
+        'dna' => 'application/vnd.dna',
+        'doc' => 'application/msword',
+        'docm' => 'application/vnd.ms-word.template.macroEnabled.12',
+        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+        'dot' => 'application/msword',
+        'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
+        'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+        'dp' => 'application/vnd.osgi.dp',
+        'dpg' => 'application/vnd.dpgraph',
+        'dpx' => 'image/dpx',
+        'dra' => 'audio/vnd.dra',
+        'drle' => 'image/dicom-rle',
+        'dsc' => 'text/prs.lines.tag',
+        'dssc' => 'application/dssc+der',
+        'dtb' => 'application/x-dtbook+xml',
+        'dtd' => 'application/xml-dtd',
+        'dts' => 'audio/vnd.dts',
+        'dtshd' => 'audio/vnd.dts.hd',
+        'dump' => 'application/octet-stream',
+        'dvb' => 'video/vnd.dvb.file',
+        'dvi' => 'application/x-dvi',
+        'dwd' => 'application/atsc-dwd+xml',
+        'dwf' => 'model/vnd.dwf',
+        'dwg' => 'image/vnd.dwg',
+        'dxf' => 'image/vnd.dxf',
+        'dxp' => 'application/vnd.spotfire.dxp',
+        'dxr' => 'application/x-director',
+        'ear' => 'application/java-archive',
+        'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+        'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+        'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+        'ecma' => 'application/ecmascript',
+        'edm' => 'application/vnd.novadigm.edm',
+        'edx' => 'application/vnd.novadigm.edx',
+        'efif' => 'application/vnd.picsel',
+        'ei6' => 'application/vnd.pg.osasli',
+        'elc' => 'application/octet-stream',
+        'emf' => 'image/emf',
+        'eml' => 'message/rfc822',
+        'emma' => 'application/emma+xml',
+        'emotionml' => 'application/emotionml+xml',
+        'emz' => 'application/x-msmetafile',
+        'eol' => 'audio/vnd.digital-winds',
+        'eot' => 'application/vnd.ms-fontobject',
+        'eps' => 'application/postscript',
+        'epub' => 'application/epub+zip',
+        'es3' => 'application/vnd.eszigno3+xml',
+        'esa' => 'application/vnd.osgi.subsystem',
+        'esf' => 'application/vnd.epson.esf',
+        'et3' => 'application/vnd.eszigno3+xml',
+        'etx' => 'text/x-setext',
+        'eva' => 'application/x-eva',
+        'evy' => 'application/x-envoy',
+        'exe' => 'application/octet-stream',
+        'exi' => 'application/exi',
+        'exp' => 'application/express',
+        'exr' => 'image/aces',
+        'ext' => 'application/vnd.novadigm.ext',
+        'ez' => 'application/andrew-inset',
+        'ez2' => 'application/vnd.ezpix-album',
+        'ez3' => 'application/vnd.ezpix-package',
+        'f' => 'text/x-fortran',
+        'f4v' => 'video/mp4',
+        'f77' => 'text/x-fortran',
+        'f90' => 'text/x-fortran',
+        'fbs' => 'image/vnd.fastbidsheet',
+        'fcdt' => 'application/vnd.adobe.formscentral.fcdt',
+        'fcs' => 'application/vnd.isac.fcs',
+        'fdf' => 'application/vnd.fdf',
+        'fdt' => 'application/fdt+xml',
+        'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+        'fg5' => 'application/vnd.fujitsu.oasysgp',
+        'fgd' => 'application/x-director',
+        'fh' => 'image/x-freehand',
+        'fh4' => 'image/x-freehand',
+        'fh5' => 'image/x-freehand',
+        'fh7' => 'image/x-freehand',
+        'fhc' => 'image/x-freehand',
+        'fig' => 'application/x-xfig',
+        'fits' => 'image/fits',
+        'flac' => 'audio/x-flac',
+        'fli' => 'video/x-fli',
+        'flo' => 'application/vnd.micrografx.flo',
+        'flv' => 'video/x-flv',
+        'flw' => 'application/vnd.kde.kivio',
+        'flx' => 'text/vnd.fmi.flexstor',
+        'fly' => 'text/vnd.fly',
+        'fm' => 'application/vnd.framemaker',
+        'fnc' => 'application/vnd.frogans.fnc',
+        'fo' => 'application/vnd.software602.filler.form+xml',
+        'for' => 'text/x-fortran',
+        'fpx' => 'image/vnd.fpx',
+        'frame' => 'application/vnd.framemaker',
+        'fsc' => 'application/vnd.fsc.weblaunch',
+        'fst' => 'image/vnd.fst',
+        'ftc' => 'application/vnd.fluxtime.clip',
+        'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+        'fvt' => 'video/vnd.fvt',
+        'fxp' => 'application/vnd.adobe.fxp',
+        'fxpl' => 'application/vnd.adobe.fxp',
+        'fzs' => 'application/vnd.fuzzysheet',
+        'g2w' => 'application/vnd.geoplan',
+        'g3' => 'image/g3fax',
+        'g3w' => 'application/vnd.geospace',
+        'gac' => 'application/vnd.groove-account',
+        'gam' => 'application/x-tads',
+        'gbr' => 'application/rpki-ghostbusters',
+        'gca' => 'application/x-gca-compressed',
+        'gdl' => 'model/vnd.gdl',
+        'gdoc' => 'application/vnd.google-apps.document',
+        'ged' => 'text/vnd.familysearch.gedcom',
+        'geo' => 'application/vnd.dynageo',
+        'geojson' => 'application/geo+json',
+        'gex' => 'application/vnd.geometry-explorer',
+        'ggb' => 'application/vnd.geogebra.file',
+        'ggt' => 'application/vnd.geogebra.tool',
+        'ghf' => 'application/vnd.groove-help',
+        'gif' => 'image/gif',
+        'gim' => 'application/vnd.groove-identity-message',
+        'glb' => 'model/gltf-binary',
+        'gltf' => 'model/gltf+json',
+        'gml' => 'application/gml+xml',
+        'gmx' => 'application/vnd.gmx',
+        'gnumeric' => 'application/x-gnumeric',
+        'gpg' => 'application/gpg-keys',
+        'gph' => 'application/vnd.flographit',
+        'gpx' => 'application/gpx+xml',
+        'gqf' => 'application/vnd.grafeq',
+        'gqs' => 'application/vnd.grafeq',
+        'gram' => 'application/srgs',
+        'gramps' => 'application/x-gramps-xml',
+        'gre' => 'application/vnd.geometry-explorer',
+        'grv' => 'application/vnd.groove-injector',
+        'grxml' => 'application/srgs+xml',
+        'gsf' => 'application/x-font-ghostscript',
+        'gsheet' => 'application/vnd.google-apps.spreadsheet',
+        'gslides' => 'application/vnd.google-apps.presentation',
+        'gtar' => 'application/x-gtar',
+        'gtm' => 'application/vnd.groove-tool-message',
+        'gtw' => 'model/vnd.gtw',
+        'gv' => 'text/vnd.graphviz',
+        'gxf' => 'application/gxf',
+        'gxt' => 'application/vnd.geonext',
+        'gz' => 'application/gzip',
+        'gzip' => 'application/gzip',
+        'h' => 'text/x-c',
+        'h261' => 'video/h261',
+        'h263' => 'video/h263',
+        'h264' => 'video/h264',
+        'hal' => 'application/vnd.hal+xml',
+        'hbci' => 'application/vnd.hbci',
+        'hbs' => 'text/x-handlebars-template',
+        'hdd' => 'application/x-virtualbox-hdd',
+        'hdf' => 'application/x-hdf',
+        'heic' => 'image/heic',
+        'heics' => 'image/heic-sequence',
+        'heif' => 'image/heif',
+        'heifs' => 'image/heif-sequence',
+        'hej2' => 'image/hej2k',
+        'held' => 'application/atsc-held+xml',
+        'hh' => 'text/x-c',
+        'hjson' => 'application/hjson',
+        'hlp' => 'application/winhlp',
+        'hpgl' => 'application/vnd.hp-hpgl',
+        'hpid' => 'application/vnd.hp-hpid',
+        'hps' => 'application/vnd.hp-hps',
+        'hqx' => 'application/mac-binhex40',
+        'hsj2' => 'image/hsj2',
+        'htc' => 'text/x-component',
+        'htke' => 'application/vnd.kenameaapp',
+        'htm' => 'text/html',
+        'html' => 'text/html',
+        'hvd' => 'application/vnd.yamaha.hv-dic',
+        'hvp' => 'application/vnd.yamaha.hv-voice',
+        'hvs' => 'application/vnd.yamaha.hv-script',
+        'i2g' => 'application/vnd.intergeo',
+        'icc' => 'application/vnd.iccprofile',
+        'ice' => 'x-conference/x-cooltalk',
+        'icm' => 'application/vnd.iccprofile',
+        'ico' => 'image/x-icon',
+        'ics' => 'text/calendar',
+        'ief' => 'image/ief',
+        'ifb' => 'text/calendar',
+        'ifm' => 'application/vnd.shana.informed.formdata',
+        'iges' => 'model/iges',
+        'igl' => 'application/vnd.igloader',
+        'igm' => 'application/vnd.insors.igm',
+        'igs' => 'model/iges',
+        'igx' => 'application/vnd.micrografx.igx',
+        'iif' => 'application/vnd.shana.informed.interchange',
+        'img' => 'application/octet-stream',
+        'imp' => 'application/vnd.accpac.simply.imp',
+        'ims' => 'application/vnd.ms-ims',
+        'in' => 'text/plain',
+        'ini' => 'text/plain',
+        'ink' => 'application/inkml+xml',
+        'inkml' => 'application/inkml+xml',
+        'install' => 'application/x-install-instructions',
+        'iota' => 'application/vnd.astraea-software.iota',
+        'ipfix' => 'application/ipfix',
+        'ipk' => 'application/vnd.shana.informed.package',
+        'irm' => 'application/vnd.ibm.rights-management',
+        'irp' => 'application/vnd.irepository.package+xml',
+        'iso' => 'application/x-iso9660-image',
+        'itp' => 'application/vnd.shana.informed.formtemplate',
+        'its' => 'application/its+xml',
+        'ivp' => 'application/vnd.immervision-ivp',
+        'ivu' => 'application/vnd.immervision-ivu',
+        'jad' => 'text/vnd.sun.j2me.app-descriptor',
+        'jade' => 'text/jade',
+        'jam' => 'application/vnd.jam',
+        'jar' => 'application/java-archive',
+        'jardiff' => 'application/x-java-archive-diff',
+        'java' => 'text/x-java-source',
+        'jhc' => 'image/jphc',
+        'jisp' => 'application/vnd.jisp',
+        'jls' => 'image/jls',
+        'jlt' => 'application/vnd.hp-jlyt',
+        'jng' => 'image/x-jng',
+        'jnlp' => 'application/x-java-jnlp-file',
+        'joda' => 'application/vnd.joost.joda-archive',
+        'jp2' => 'image/jp2',
+        'jpe' => 'image/jpeg',
+        'jpeg' => 'image/jpeg',
+        'jpf' => 'image/jpx',
+        'jpg' => 'image/jpeg',
+        'jpg2' => 'image/jp2',
+        'jpgm' => 'video/jpm',
+        'jpgv' => 'video/jpeg',
+        'jph' => 'image/jph',
+        'jpm' => 'video/jpm',
+        'jpx' => 'image/jpx',
+        'js' => 'application/javascript',
+        'json' => 'application/json',
+        'json5' => 'application/json5',
+        'jsonld' => 'application/ld+json',
+        'jsonml' => 'application/jsonml+json',
+        'jsx' => 'text/jsx',
+        'jt' => 'model/jt',
+        'jxr' => 'image/jxr',
+        'jxra' => 'image/jxra',
+        'jxrs' => 'image/jxrs',
+        'jxs' => 'image/jxs',
+        'jxsc' => 'image/jxsc',
+        'jxsi' => 'image/jxsi',
+        'jxss' => 'image/jxss',
+        'kar' => 'audio/midi',
+        'karbon' => 'application/vnd.kde.karbon',
+        'kdb' => 'application/octet-stream',
+        'kdbx' => 'application/x-keepass2',
+        'key' => 'application/x-iwork-keynote-sffkey',
+        'kfo' => 'application/vnd.kde.kformula',
+        'kia' => 'application/vnd.kidspiration',
+        'kml' => 'application/vnd.google-earth.kml+xml',
+        'kmz' => 'application/vnd.google-earth.kmz',
+        'kne' => 'application/vnd.kinar',
+        'knp' => 'application/vnd.kinar',
+        'kon' => 'application/vnd.kde.kontour',
+        'kpr' => 'application/vnd.kde.kpresenter',
+        'kpt' => 'application/vnd.kde.kpresenter',
+        'kpxx' => 'application/vnd.ds-keypoint',
+        'ksp' => 'application/vnd.kde.kspread',
+        'ktr' => 'application/vnd.kahootz',
+        'ktx' => 'image/ktx',
+        'ktx2' => 'image/ktx2',
+        'ktz' => 'application/vnd.kahootz',
+        'kwd' => 'application/vnd.kde.kword',
+        'kwt' => 'application/vnd.kde.kword',
+        'lasxml' => 'application/vnd.las.las+xml',
+        'latex' => 'application/x-latex',
+        'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+        'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+        'les' => 'application/vnd.hhe.lesson-player',
+        'less' => 'text/less',
+        'lgr' => 'application/lgr+xml',
+        'lha' => 'application/octet-stream',
+        'link66' => 'application/vnd.route66.link66+xml',
+        'list' => 'text/plain',
+        'list3820' => 'application/vnd.ibm.modcap',
+        'listafp' => 'application/vnd.ibm.modcap',
+        'litcoffee' => 'text/coffeescript',
+        'lnk' => 'application/x-ms-shortcut',
+        'log' => 'text/plain',
+        'lostxml' => 'application/lost+xml',
+        'lrf' => 'application/octet-stream',
+        'lrm' => 'application/vnd.ms-lrm',
+        'ltf' => 'application/vnd.frogans.ltf',
+        'lua' => 'text/x-lua',
+        'luac' => 'application/x-lua-bytecode',
+        'lvp' => 'audio/vnd.lucent.voice',
+        'lwp' => 'application/vnd.lotus-wordpro',
+        'lzh' => 'application/octet-stream',
+        'm1v' => 'video/mpeg',
+        'm2a' => 'audio/mpeg',
+        'm2v' => 'video/mpeg',
+        'm3a' => 'audio/mpeg',
+        'm3u' => 'text/plain',
+        'm3u8' => 'application/vnd.apple.mpegurl',
+        'm4a' => 'audio/x-m4a',
+        'm4p' => 'application/mp4',
+        'm4s' => 'video/iso.segment',
+        'm4u' => 'application/vnd.mpegurl',
+        'm4v' => 'video/x-m4v',
+        'm13' => 'application/x-msmediaview',
+        'm14' => 'application/x-msmediaview',
+        'm21' => 'application/mp21',
+        'ma' => 'application/mathematica',
+        'mads' => 'application/mads+xml',
+        'maei' => 'application/mmt-aei+xml',
+        'mag' => 'application/vnd.ecowin.chart',
+        'maker' => 'application/vnd.framemaker',
+        'man' => 'text/troff',
+        'manifest' => 'text/cache-manifest',
+        'map' => 'application/json',
+        'mar' => 'application/octet-stream',
+        'markdown' => 'text/markdown',
+        'mathml' => 'application/mathml+xml',
+        'mb' => 'application/mathematica',
+        'mbk' => 'application/vnd.mobius.mbk',
+        'mbox' => 'application/mbox',
+        'mc1' => 'application/vnd.medcalcdata',
+        'mcd' => 'application/vnd.mcd',
+        'mcurl' => 'text/vnd.curl.mcurl',
+        'md' => 'text/markdown',
+        'mdb' => 'application/x-msaccess',
+        'mdi' => 'image/vnd.ms-modi',
+        'mdx' => 'text/mdx',
+        'me' => 'text/troff',
+        'mesh' => 'model/mesh',
+        'meta4' => 'application/metalink4+xml',
+        'metalink' => 'application/metalink+xml',
+        'mets' => 'application/mets+xml',
+        'mfm' => 'application/vnd.mfmp',
+        'mft' => 'application/rpki-manifest',
+        'mgp' => 'application/vnd.osgeo.mapguide.package',
+        'mgz' => 'application/vnd.proteus.magazine',
+        'mid' => 'audio/midi',
+        'midi' => 'audio/midi',
+        'mie' => 'application/x-mie',
+        'mif' => 'application/vnd.mif',
+        'mime' => 'message/rfc822',
+        'mj2' => 'video/mj2',
+        'mjp2' => 'video/mj2',
+        'mjs' => 'text/javascript',
+        'mk3d' => 'video/x-matroska',
+        'mka' => 'audio/x-matroska',
+        'mkd' => 'text/x-markdown',
+        'mks' => 'video/x-matroska',
+        'mkv' => 'video/x-matroska',
+        'mlp' => 'application/vnd.dolby.mlp',
+        'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+        'mmf' => 'application/vnd.smaf',
+        'mml' => 'text/mathml',
+        'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+        'mng' => 'video/x-mng',
+        'mny' => 'application/x-msmoney',
+        'mobi' => 'application/x-mobipocket-ebook',
+        'mods' => 'application/mods+xml',
+        'mov' => 'video/quicktime',
+        'movie' => 'video/x-sgi-movie',
+        'mp2' => 'audio/mpeg',
+        'mp2a' => 'audio/mpeg',
+        'mp3' => 'audio/mpeg',
+        'mp4' => 'video/mp4',
+        'mp4a' => 'audio/mp4',
+        'mp4s' => 'application/mp4',
+        'mp4v' => 'video/mp4',
+        'mp21' => 'application/mp21',
+        'mpc' => 'application/vnd.mophun.certificate',
+        'mpd' => 'application/dash+xml',
+        'mpe' => 'video/mpeg',
+        'mpeg' => 'video/mpeg',
+        'mpf' => 'application/media-policy-dataset+xml',
+        'mpg' => 'video/mpeg',
+        'mpg4' => 'video/mp4',
+        'mpga' => 'audio/mpeg',
+        'mpkg' => 'application/vnd.apple.installer+xml',
+        'mpm' => 'application/vnd.blueice.multipass',
+        'mpn' => 'application/vnd.mophun.application',
+        'mpp' => 'application/vnd.ms-project',
+        'mpt' => 'application/vnd.ms-project',
+        'mpy' => 'application/vnd.ibm.minipay',
+        'mqy' => 'application/vnd.mobius.mqy',
+        'mrc' => 'application/marc',
+        'mrcx' => 'application/marcxml+xml',
+        'ms' => 'text/troff',
+        'mscml' => 'application/mediaservercontrol+xml',
+        'mseed' => 'application/vnd.fdsn.mseed',
+        'mseq' => 'application/vnd.mseq',
+        'msf' => 'application/vnd.epson.msf',
+        'msg' => 'application/vnd.ms-outlook',
+        'msh' => 'model/mesh',
+        'msi' => 'application/x-msdownload',
+        'msix' => 'application/msix',
+        'msixbundle' => 'application/msixbundle',
+        'msl' => 'application/vnd.mobius.msl',
+        'msm' => 'application/octet-stream',
+        'msp' => 'application/octet-stream',
+        'msty' => 'application/vnd.muvee.style',
+        'mtl' => 'model/mtl',
+        'mts' => 'model/vnd.mts',
+        'mus' => 'application/vnd.musician',
+        'musd' => 'application/mmt-usd+xml',
+        'musicxml' => 'application/vnd.recordare.musicxml+xml',
+        'mvb' => 'application/x-msmediaview',
+        'mvt' => 'application/vnd.mapbox-vector-tile',
+        'mwf' => 'application/vnd.mfer',
+        'mxf' => 'application/mxf',
+        'mxl' => 'application/vnd.recordare.musicxml',
+        'mxmf' => 'audio/mobile-xmf',
+        'mxml' => 'application/xv+xml',
+        'mxs' => 'application/vnd.triscape.mxs',
+        'mxu' => 'video/vnd.mpegurl',
+        'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+        'n3' => 'text/n3',
+        'nb' => 'application/mathematica',
+        'nbp' => 'application/vnd.wolfram.player',
+        'nc' => 'application/x-netcdf',
+        'ncx' => 'application/x-dtbncx+xml',
+        'nfo' => 'text/x-nfo',
+        'ngdat' => 'application/vnd.nokia.n-gage.data',
+        'nitf' => 'application/vnd.nitf',
+        'nlu' => 'application/vnd.neurolanguage.nlu',
+        'nml' => 'application/vnd.enliven',
+        'nnd' => 'application/vnd.noblenet-directory',
+        'nns' => 'application/vnd.noblenet-sealer',
+        'nnw' => 'application/vnd.noblenet-web',
+        'npx' => 'image/vnd.net-fpx',
+        'nq' => 'application/n-quads',
+        'nsc' => 'application/x-conference',
+        'nsf' => 'application/vnd.lotus-notes',
+        'nt' => 'application/n-triples',
+        'ntf' => 'application/vnd.nitf',
+        'numbers' => 'application/x-iwork-numbers-sffnumbers',
+        'nzb' => 'application/x-nzb',
+        'oa2' => 'application/vnd.fujitsu.oasys2',
+        'oa3' => 'application/vnd.fujitsu.oasys3',
+        'oas' => 'application/vnd.fujitsu.oasys',
+        'obd' => 'application/x-msbinder',
+        'obgx' => 'application/vnd.openblox.game+xml',
+        'obj' => 'model/obj',
+        'oda' => 'application/oda',
+        'odb' => 'application/vnd.oasis.opendocument.database',
+        'odc' => 'application/vnd.oasis.opendocument.chart',
+        'odf' => 'application/vnd.oasis.opendocument.formula',
+        'odft' => 'application/vnd.oasis.opendocument.formula-template',
+        'odg' => 'application/vnd.oasis.opendocument.graphics',
+        'odi' => 'application/vnd.oasis.opendocument.image',
+        'odm' => 'application/vnd.oasis.opendocument.text-master',
+        'odp' => 'application/vnd.oasis.opendocument.presentation',
+        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+        'odt' => 'application/vnd.oasis.opendocument.text',
+        'oga' => 'audio/ogg',
+        'ogex' => 'model/vnd.opengex',
+        'ogg' => 'audio/ogg',
+        'ogv' => 'video/ogg',
+        'ogx' => 'application/ogg',
+        'omdoc' => 'application/omdoc+xml',
+        'onepkg' => 'application/onenote',
+        'onetmp' => 'application/onenote',
+        'onetoc' => 'application/onenote',
+        'onetoc2' => 'application/onenote',
+        'opf' => 'application/oebps-package+xml',
+        'opml' => 'text/x-opml',
+        'oprc' => 'application/vnd.palm',
+        'opus' => 'audio/ogg',
+        'org' => 'text/x-org',
+        'osf' => 'application/vnd.yamaha.openscoreformat',
+        'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+        'osm' => 'application/vnd.openstreetmap.data+xml',
+        'otc' => 'application/vnd.oasis.opendocument.chart-template',
+        'otf' => 'font/otf',
+        'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+        'oth' => 'application/vnd.oasis.opendocument.text-web',
+        'oti' => 'application/vnd.oasis.opendocument.image-template',
+        'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+        'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+        'ott' => 'application/vnd.oasis.opendocument.text-template',
+        'ova' => 'application/x-virtualbox-ova',
+        'ovf' => 'application/x-virtualbox-ovf',
+        'owl' => 'application/rdf+xml',
+        'oxps' => 'application/oxps',
+        'oxt' => 'application/vnd.openofficeorg.extension',
+        'p' => 'text/x-pascal',
+        'p7a' => 'application/x-pkcs7-signature',
+        'p7b' => 'application/x-pkcs7-certificates',
+        'p7c' => 'application/pkcs7-mime',
+        'p7m' => 'application/pkcs7-mime',
+        'p7r' => 'application/x-pkcs7-certreqresp',
+        'p7s' => 'application/pkcs7-signature',
+        'p8' => 'application/pkcs8',
+        'p10' => 'application/x-pkcs10',
+        'p12' => 'application/x-pkcs12',
+        'pac' => 'application/x-ns-proxy-autoconfig',
+        'pages' => 'application/x-iwork-pages-sffpages',
+        'pas' => 'text/x-pascal',
+        'paw' => 'application/vnd.pawaafile',
+        'pbd' => 'application/vnd.powerbuilder6',
+        'pbm' => 'image/x-portable-bitmap',
+        'pcap' => 'application/vnd.tcpdump.pcap',
+        'pcf' => 'application/x-font-pcf',
+        'pcl' => 'application/vnd.hp-pcl',
+        'pclxl' => 'application/vnd.hp-pclxl',
+        'pct' => 'image/x-pict',
+        'pcurl' => 'application/vnd.curl.pcurl',
+        'pcx' => 'image/x-pcx',
+        'pdb' => 'application/x-pilot',
+        'pde' => 'text/x-processing',
+        'pdf' => 'application/pdf',
+        'pem' => 'application/x-x509-user-cert',
+        'pfa' => 'application/x-font-type1',
+        'pfb' => 'application/x-font-type1',
+        'pfm' => 'application/x-font-type1',
+        'pfr' => 'application/font-tdpfr',
+        'pfx' => 'application/x-pkcs12',
+        'pgm' => 'image/x-portable-graymap',
+        'pgn' => 'application/x-chess-pgn',
+        'pgp' => 'application/pgp',
+        'phar' => 'application/octet-stream',
+        'php' => 'application/x-httpd-php',
+        'php3' => 'application/x-httpd-php',
+        'php4' => 'application/x-httpd-php',
+        'phps' => 'application/x-httpd-php-source',
+        'phtml' => 'application/x-httpd-php',
+        'pic' => 'image/x-pict',
+        'pkg' => 'application/octet-stream',
+        'pki' => 'application/pkixcmp',
+        'pkipath' => 'application/pkix-pkipath',
+        'pkpass' => 'application/vnd.apple.pkpass',
+        'pl' => 'application/x-perl',
+        'plb' => 'application/vnd.3gpp.pic-bw-large',
+        'plc' => 'application/vnd.mobius.plc',
+        'plf' => 'application/vnd.pocketlearn',
+        'pls' => 'application/pls+xml',
+        'pm' => 'application/x-perl',
+        'pml' => 'application/vnd.ctc-posml',
+        'png' => 'image/png',
+        'pnm' => 'image/x-portable-anymap',
+        'portpkg' => 'application/vnd.macports.portpkg',
+        'pot' => 'application/vnd.ms-powerpoint',
+        'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
+        'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+        'ppa' => 'application/vnd.ms-powerpoint',
+        'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
+        'ppd' => 'application/vnd.cups-ppd',
+        'ppm' => 'image/x-portable-pixmap',
+        'pps' => 'application/vnd.ms-powerpoint',
+        'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
+        'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+        'ppt' => 'application/powerpoint',
+        'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
+        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+        'pqa' => 'application/vnd.palm',
+        'prc' => 'model/prc',
+        'pre' => 'application/vnd.lotus-freelance',
+        'prf' => 'application/pics-rules',
+        'provx' => 'application/provenance+xml',
+        'ps' => 'application/postscript',
+        'psb' => 'application/vnd.3gpp.pic-bw-small',
+        'psd' => 'application/x-photoshop',
+        'psf' => 'application/x-font-linux-psf',
+        'pskcxml' => 'application/pskc+xml',
+        'pti' => 'image/prs.pti',
+        'ptid' => 'application/vnd.pvi.ptid1',
+        'pub' => 'application/x-mspublisher',
+        'pvb' => 'application/vnd.3gpp.pic-bw-var',
+        'pwn' => 'application/vnd.3m.post-it-notes',
+        'pya' => 'audio/vnd.ms-playready.media.pya',
+        'pyo' => 'model/vnd.pytha.pyox',
+        'pyox' => 'model/vnd.pytha.pyox',
+        'pyv' => 'video/vnd.ms-playready.media.pyv',
+        'qam' => 'application/vnd.epson.quickanime',
+        'qbo' => 'application/vnd.intu.qbo',
+        'qfx' => 'application/vnd.intu.qfx',
+        'qps' => 'application/vnd.publishare-delta-tree',
+        'qt' => 'video/quicktime',
+        'qwd' => 'application/vnd.quark.quarkxpress',
+        'qwt' => 'application/vnd.quark.quarkxpress',
+        'qxb' => 'application/vnd.quark.quarkxpress',
+        'qxd' => 'application/vnd.quark.quarkxpress',
+        'qxl' => 'application/vnd.quark.quarkxpress',
+        'qxt' => 'application/vnd.quark.quarkxpress',
+        'ra' => 'audio/x-realaudio',
+        'ram' => 'audio/x-pn-realaudio',
+        'raml' => 'application/raml+yaml',
+        'rapd' => 'application/route-apd+xml',
+        'rar' => 'application/x-rar',
+        'ras' => 'image/x-cmu-raster',
+        'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+        'rdf' => 'application/rdf+xml',
+        'rdz' => 'application/vnd.data-vision.rdz',
+        'relo' => 'application/p2p-overlay+xml',
+        'rep' => 'application/vnd.businessobjects',
+        'res' => 'application/x-dtbresource+xml',
+        'rgb' => 'image/x-rgb',
+        'rif' => 'application/reginfo+xml',
+        'rip' => 'audio/vnd.rip',
+        'ris' => 'application/x-research-info-systems',
+        'rl' => 'application/resource-lists+xml',
+        'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+        'rld' => 'application/resource-lists-diff+xml',
+        'rm' => 'audio/x-pn-realaudio',
+        'rmi' => 'audio/midi',
+        'rmp' => 'audio/x-pn-realaudio-plugin',
+        'rms' => 'application/vnd.jcp.javame.midlet-rms',
+        'rmvb' => 'application/vnd.rn-realmedia-vbr',
+        'rnc' => 'application/relax-ng-compact-syntax',
+        'rng' => 'application/xml',
+        'roa' => 'application/rpki-roa',
+        'roff' => 'text/troff',
+        'rp9' => 'application/vnd.cloanto.rp9',
+        'rpm' => 'audio/x-pn-realaudio-plugin',
+        'rpss' => 'application/vnd.nokia.radio-presets',
+        'rpst' => 'application/vnd.nokia.radio-preset',
+        'rq' => 'application/sparql-query',
+        'rs' => 'application/rls-services+xml',
+        'rsa' => 'application/x-pkcs7',
+        'rsat' => 'application/atsc-rsat+xml',
+        'rsd' => 'application/rsd+xml',
+        'rsheet' => 'application/urc-ressheet+xml',
+        'rss' => 'application/rss+xml',
+        'rtf' => 'text/rtf',
+        'rtx' => 'text/richtext',
+        'run' => 'application/x-makeself',
+        'rusd' => 'application/route-usd+xml',
+        'rv' => 'video/vnd.rn-realvideo',
+        's' => 'text/x-asm',
+        's3m' => 'audio/s3m',
+        'saf' => 'application/vnd.yamaha.smaf-audio',
+        'sass' => 'text/x-sass',
+        'sbml' => 'application/sbml+xml',
+        'sc' => 'application/vnd.ibm.secure-container',
+        'scd' => 'application/x-msschedule',
+        'scm' => 'application/vnd.lotus-screencam',
+        'scq' => 'application/scvp-cv-request',
+        'scs' => 'application/scvp-cv-response',
+        'scss' => 'text/x-scss',
+        'scurl' => 'text/vnd.curl.scurl',
+        'sda' => 'application/vnd.stardivision.draw',
+        'sdc' => 'application/vnd.stardivision.calc',
+        'sdd' => 'application/vnd.stardivision.impress',
+        'sdkd' => 'application/vnd.solent.sdkm+xml',
+        'sdkm' => 'application/vnd.solent.sdkm+xml',
+        'sdp' => 'application/sdp',
+        'sdw' => 'application/vnd.stardivision.writer',
+        'sea' => 'application/octet-stream',
+        'see' => 'application/vnd.seemail',
+        'seed' => 'application/vnd.fdsn.seed',
+        'sema' => 'application/vnd.sema',
+        'semd' => 'application/vnd.semd',
+        'semf' => 'application/vnd.semf',
+        'senmlx' => 'application/senml+xml',
+        'sensmlx' => 'application/sensml+xml',
+        'ser' => 'application/java-serialized-object',
+        'setpay' => 'application/set-payment-initiation',
+        'setreg' => 'application/set-registration-initiation',
+        'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+        'sfs' => 'application/vnd.spotfire.sfs',
+        'sfv' => 'text/x-sfv',
+        'sgi' => 'image/sgi',
+        'sgl' => 'application/vnd.stardivision.writer-global',
+        'sgm' => 'text/sgml',
+        'sgml' => 'text/sgml',
+        'sh' => 'application/x-sh',
+        'shar' => 'application/x-shar',
+        'shex' => 'text/shex',
+        'shf' => 'application/shf+xml',
+        'shtml' => 'text/html',
+        'sid' => 'image/x-mrsid-image',
+        'sieve' => 'application/sieve',
+        'sig' => 'application/pgp-signature',
+        'sil' => 'audio/silk',
+        'silo' => 'model/mesh',
+        'sis' => 'application/vnd.symbian.install',
+        'sisx' => 'application/vnd.symbian.install',
+        'sit' => 'application/x-stuffit',
+        'sitx' => 'application/x-stuffitx',
+        'siv' => 'application/sieve',
+        'skd' => 'application/vnd.koan',
+        'skm' => 'application/vnd.koan',
+        'skp' => 'application/vnd.koan',
+        'skt' => 'application/vnd.koan',
+        'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+        'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+        'slim' => 'text/slim',
+        'slm' => 'text/slim',
+        'sls' => 'application/route-s-tsid+xml',
+        'slt' => 'application/vnd.epson.salt',
+        'sm' => 'application/vnd.stepmania.stepchart',
+        'smf' => 'application/vnd.stardivision.math',
+        'smi' => 'application/smil',
+        'smil' => 'application/smil',
+        'smv' => 'video/x-smv',
+        'smzip' => 'application/vnd.stepmania.package',
+        'snd' => 'audio/basic',
+        'snf' => 'application/x-font-snf',
+        'so' => 'application/octet-stream',
+        'spc' => 'application/x-pkcs7-certificates',
+        'spdx' => 'text/spdx',
+        'spf' => 'application/vnd.yamaha.smaf-phrase',
+        'spl' => 'application/x-futuresplash',
+        'spot' => 'text/vnd.in3d.spot',
+        'spp' => 'application/scvp-vp-response',
+        'spq' => 'application/scvp-vp-request',
+        'spx' => 'audio/ogg',
+        'sql' => 'application/x-sql',
+        'src' => 'application/x-wais-source',
+        'srt' => 'application/x-subrip',
+        'sru' => 'application/sru+xml',
+        'srx' => 'application/sparql-results+xml',
+        'ssdl' => 'application/ssdl+xml',
+        'sse' => 'application/vnd.kodak-descriptor',
+        'ssf' => 'application/vnd.epson.ssf',
+        'ssml' => 'application/ssml+xml',
+        'sst' => 'application/octet-stream',
+        'st' => 'application/vnd.sailingtracker.track',
+        'stc' => 'application/vnd.sun.xml.calc.template',
+        'std' => 'application/vnd.sun.xml.draw.template',
+        'step' => 'application/STEP',
+        'stf' => 'application/vnd.wt.stf',
+        'sti' => 'application/vnd.sun.xml.impress.template',
+        'stk' => 'application/hyperstudio',
+        'stl' => 'model/stl',
+        'stp' => 'application/STEP',
+        'stpx' => 'model/step+xml',
+        'stpxz' => 'model/step-xml+zip',
+        'stpz' => 'model/step+zip',
+        'str' => 'application/vnd.pg.format',
+        'stw' => 'application/vnd.sun.xml.writer.template',
+        'styl' => 'text/stylus',
+        'stylus' => 'text/stylus',
+        'sub' => 'text/vnd.dvb.subtitle',
+        'sus' => 'application/vnd.sus-calendar',
+        'susp' => 'application/vnd.sus-calendar',
+        'sv4cpio' => 'application/x-sv4cpio',
+        'sv4crc' => 'application/x-sv4crc',
+        'svc' => 'application/vnd.dvb.service',
+        'svd' => 'application/vnd.svd',
+        'svg' => 'image/svg+xml',
+        'svgz' => 'image/svg+xml',
+        'swa' => 'application/x-director',
+        'swf' => 'application/x-shockwave-flash',
+        'swi' => 'application/vnd.aristanetworks.swi',
+        'swidtag' => 'application/swid+xml',
+        'sxc' => 'application/vnd.sun.xml.calc',
+        'sxd' => 'application/vnd.sun.xml.draw',
+        'sxg' => 'application/vnd.sun.xml.writer.global',
+        'sxi' => 'application/vnd.sun.xml.impress',
+        'sxm' => 'application/vnd.sun.xml.math',
+        'sxw' => 'application/vnd.sun.xml.writer',
+        't' => 'text/troff',
+        't3' => 'application/x-t3vm-image',
+        't38' => 'image/t38',
+        'taglet' => 'application/vnd.mynfc',
+        'tao' => 'application/vnd.tao.intent-module-archive',
+        'tap' => 'image/vnd.tencent.tap',
+        'tar' => 'application/x-tar',
+        'tcap' => 'application/vnd.3gpp2.tcap',
+        'tcl' => 'application/x-tcl',
+        'td' => 'application/urc-targetdesc+xml',
+        'teacher' => 'application/vnd.smart.teacher',
+        'tei' => 'application/tei+xml',
+        'teicorpus' => 'application/tei+xml',
+        'tex' => 'application/x-tex',
+        'texi' => 'application/x-texinfo',
+        'texinfo' => 'application/x-texinfo',
+        'text' => 'text/plain',
+        'tfi' => 'application/thraud+xml',
+        'tfm' => 'application/x-tex-tfm',
+        'tfx' => 'image/tiff-fx',
+        'tga' => 'image/x-tga',
+        'tgz' => 'application/x-tar',
+        'thmx' => 'application/vnd.ms-officetheme',
+        'tif' => 'image/tiff',
+        'tiff' => 'image/tiff',
+        'tk' => 'application/x-tcl',
+        'tmo' => 'application/vnd.tmobile-livetv',
+        'toml' => 'application/toml',
+        'torrent' => 'application/x-bittorrent',
+        'tpl' => 'application/vnd.groove-tool-template',
+        'tpt' => 'application/vnd.trid.tpt',
+        'tr' => 'text/troff',
+        'tra' => 'application/vnd.trueapp',
+        'trig' => 'application/trig',
+        'trm' => 'application/x-msterminal',
+        'ts' => 'video/mp2t',
+        'tsd' => 'application/timestamped-data',
+        'tsv' => 'text/tab-separated-values',
+        'ttc' => 'font/collection',
+        'ttf' => 'font/ttf',
+        'ttl' => 'text/turtle',
+        'ttml' => 'application/ttml+xml',
+        'twd' => 'application/vnd.simtech-mindmapper',
+        'twds' => 'application/vnd.simtech-mindmapper',
+        'txd' => 'application/vnd.genomatix.tuxedo',
+        'txf' => 'application/vnd.mobius.txf',
+        'txt' => 'text/plain',
+        'u3d' => 'model/u3d',
+        'u8dsn' => 'message/global-delivery-status',
+        'u8hdr' => 'message/global-headers',
+        'u8mdn' => 'message/global-disposition-notification',
+        'u8msg' => 'message/global',
+        'u32' => 'application/x-authorware-bin',
+        'ubj' => 'application/ubjson',
+        'udeb' => 'application/x-debian-package',
+        'ufd' => 'application/vnd.ufdl',
+        'ufdl' => 'application/vnd.ufdl',
+        'ulx' => 'application/x-glulx',
+        'umj' => 'application/vnd.umajin',
+        'unityweb' => 'application/vnd.unity',
+        'uo' => 'application/vnd.uoml+xml',
+        'uoml' => 'application/vnd.uoml+xml',
+        'uri' => 'text/uri-list',
+        'uris' => 'text/uri-list',
+        'urls' => 'text/uri-list',
+        'usda' => 'model/vnd.usda',
+        'usdz' => 'model/vnd.usdz+zip',
+        'ustar' => 'application/x-ustar',
+        'utz' => 'application/vnd.uiq.theme',
+        'uu' => 'text/x-uuencode',
+        'uva' => 'audio/vnd.dece.audio',
+        'uvd' => 'application/vnd.dece.data',
+        'uvf' => 'application/vnd.dece.data',
+        'uvg' => 'image/vnd.dece.graphic',
+        'uvh' => 'video/vnd.dece.hd',
+        'uvi' => 'image/vnd.dece.graphic',
+        'uvm' => 'video/vnd.dece.mobile',
+        'uvp' => 'video/vnd.dece.pd',
+        'uvs' => 'video/vnd.dece.sd',
+        'uvt' => 'application/vnd.dece.ttml+xml',
+        'uvu' => 'video/vnd.uvvu.mp4',
+        'uvv' => 'video/vnd.dece.video',
+        'uvva' => 'audio/vnd.dece.audio',
+        'uvvd' => 'application/vnd.dece.data',
+        'uvvf' => 'application/vnd.dece.data',
+        'uvvg' => 'image/vnd.dece.graphic',
+        'uvvh' => 'video/vnd.dece.hd',
+        'uvvi' => 'image/vnd.dece.graphic',
+        'uvvm' => 'video/vnd.dece.mobile',
+        'uvvp' => 'video/vnd.dece.pd',
+        'uvvs' => 'video/vnd.dece.sd',
+        'uvvt' => 'application/vnd.dece.ttml+xml',
+        'uvvu' => 'video/vnd.uvvu.mp4',
+        'uvvv' => 'video/vnd.dece.video',
+        'uvvx' => 'application/vnd.dece.unspecified',
+        'uvvz' => 'application/vnd.dece.zip',
+        'uvx' => 'application/vnd.dece.unspecified',
+        'uvz' => 'application/vnd.dece.zip',
+        'vbox' => 'application/x-virtualbox-vbox',
+        'vbox-extpack' => 'application/x-virtualbox-vbox-extpack',
+        'vcard' => 'text/vcard',
+        'vcd' => 'application/x-cdlink',
+        'vcf' => 'text/x-vcard',
+        'vcg' => 'application/vnd.groove-vcard',
+        'vcs' => 'text/x-vcalendar',
+        'vcx' => 'application/vnd.vcx',
+        'vdi' => 'application/x-virtualbox-vdi',
+        'vds' => 'model/vnd.sap.vds',
+        'vhd' => 'application/x-virtualbox-vhd',
+        'vis' => 'application/vnd.visionary',
+        'viv' => 'video/vnd.vivo',
+        'vlc' => 'application/videolan',
+        'vmdk' => 'application/x-virtualbox-vmdk',
+        'vob' => 'video/x-ms-vob',
+        'vor' => 'application/vnd.stardivision.writer',
+        'vox' => 'application/x-authorware-bin',
+        'vrml' => 'model/vrml',
+        'vsd' => 'application/vnd.visio',
+        'vsf' => 'application/vnd.vsf',
+        'vss' => 'application/vnd.visio',
+        'vst' => 'application/vnd.visio',
+        'vsw' => 'application/vnd.visio',
+        'vtf' => 'image/vnd.valve.source.texture',
+        'vtt' => 'text/vtt',
+        'vtu' => 'model/vnd.vtu',
+        'vxml' => 'application/voicexml+xml',
+        'w3d' => 'application/x-director',
+        'wad' => 'application/x-doom',
+        'wadl' => 'application/vnd.sun.wadl+xml',
+        'war' => 'application/java-archive',
+        'wasm' => 'application/wasm',
+        'wav' => 'audio/x-wav',
+        'wax' => 'audio/x-ms-wax',
+        'wbmp' => 'image/vnd.wap.wbmp',
+        'wbs' => 'application/vnd.criticaltools.wbs+xml',
+        'wbxml' => 'application/wbxml',
+        'wcm' => 'application/vnd.ms-works',
+        'wdb' => 'application/vnd.ms-works',
+        'wdp' => 'image/vnd.ms-photo',
+        'weba' => 'audio/webm',
+        'webapp' => 'application/x-web-app-manifest+json',
+        'webm' => 'video/webm',
+        'webmanifest' => 'application/manifest+json',
+        'webp' => 'image/webp',
+        'wg' => 'application/vnd.pmi.widget',
+        'wgsl' => 'text/wgsl',
+        'wgt' => 'application/widget',
+        'wif' => 'application/watcherinfo+xml',
+        'wks' => 'application/vnd.ms-works',
+        'wm' => 'video/x-ms-wm',
+        'wma' => 'audio/x-ms-wma',
+        'wmd' => 'application/x-ms-wmd',
+        'wmf' => 'image/wmf',
+        'wml' => 'text/vnd.wap.wml',
+        'wmlc' => 'application/wmlc',
+        'wmls' => 'text/vnd.wap.wmlscript',
+        'wmlsc' => 'application/vnd.wap.wmlscriptc',
+        'wmv' => 'video/x-ms-wmv',
+        'wmx' => 'video/x-ms-wmx',
+        'wmz' => 'application/x-msmetafile',
+        'woff' => 'font/woff',
+        'woff2' => 'font/woff2',
+        'word' => 'application/msword',
+        'wpd' => 'application/vnd.wordperfect',
+        'wpl' => 'application/vnd.ms-wpl',
+        'wps' => 'application/vnd.ms-works',
+        'wqd' => 'application/vnd.wqd',
+        'wri' => 'application/x-mswrite',
+        'wrl' => 'model/vrml',
+        'wsc' => 'message/vnd.wfa.wsc',
+        'wsdl' => 'application/wsdl+xml',
+        'wspolicy' => 'application/wspolicy+xml',
+        'wtb' => 'application/vnd.webturbo',
+        'wvx' => 'video/x-ms-wvx',
+        'x3d' => 'model/x3d+xml',
+        'x3db' => 'model/x3d+fastinfoset',
+        'x3dbz' => 'model/x3d+binary',
+        'x3dv' => 'model/x3d-vrml',
+        'x3dvz' => 'model/x3d+vrml',
+        'x3dz' => 'model/x3d+xml',
+        'x32' => 'application/x-authorware-bin',
+        'x_b' => 'model/vnd.parasolid.transmit.binary',
+        'x_t' => 'model/vnd.parasolid.transmit.text',
+        'xaml' => 'application/xaml+xml',
+        'xap' => 'application/x-silverlight-app',
+        'xar' => 'application/vnd.xara',
+        'xav' => 'application/xcap-att+xml',
+        'xbap' => 'application/x-ms-xbap',
+        'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+        'xbm' => 'image/x-xbitmap',
+        'xca' => 'application/xcap-caps+xml',
+        'xcs' => 'application/calendar+xml',
+        'xdf' => 'application/xcap-diff+xml',
+        'xdm' => 'application/vnd.syncml.dm+xml',
+        'xdp' => 'application/vnd.adobe.xdp+xml',
+        'xdssc' => 'application/dssc+xml',
+        'xdw' => 'application/vnd.fujixerox.docuworks',
+        'xel' => 'application/xcap-el+xml',
+        'xenc' => 'application/xenc+xml',
+        'xer' => 'application/patch-ops-error+xml',
+        'xfdf' => 'application/xfdf',
+        'xfdl' => 'application/vnd.xfdl',
+        'xht' => 'application/xhtml+xml',
+        'xhtm' => 'application/vnd.pwg-xhtml-print+xml',
+        'xhtml' => 'application/xhtml+xml',
+        'xhvml' => 'application/xv+xml',
+        'xif' => 'image/vnd.xiff',
+        'xl' => 'application/excel',
+        'xla' => 'application/vnd.ms-excel',
+        'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+        'xlc' => 'application/vnd.ms-excel',
+        'xlf' => 'application/xliff+xml',
+        'xlm' => 'application/vnd.ms-excel',
+        'xls' => 'application/vnd.ms-excel',
+        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+        'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
+        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        'xlt' => 'application/vnd.ms-excel',
+        'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
+        'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+        'xlw' => 'application/vnd.ms-excel',
+        'xm' => 'audio/xm',
+        'xml' => 'application/xml',
+        'xns' => 'application/xcap-ns+xml',
+        'xo' => 'application/vnd.olpc-sugar',
+        'xop' => 'application/xop+xml',
+        'xpi' => 'application/x-xpinstall',
+        'xpl' => 'application/xproc+xml',
+        'xpm' => 'image/x-xpixmap',
+        'xpr' => 'application/vnd.is-xpr',
+        'xps' => 'application/vnd.ms-xpsdocument',
+        'xpw' => 'application/vnd.intercon.formnet',
+        'xpx' => 'application/vnd.intercon.formnet',
+        'xsd' => 'application/xml',
+        'xsf' => 'application/prs.xsf+xml',
+        'xsl' => 'application/xml',
+        'xslt' => 'application/xslt+xml',
+        'xsm' => 'application/vnd.syncml+xml',
+        'xspf' => 'application/xspf+xml',
+        'xul' => 'application/vnd.mozilla.xul+xml',
+        'xvm' => 'application/xv+xml',
+        'xvml' => 'application/xv+xml',
+        'xwd' => 'image/x-xwindowdump',
+        'xyz' => 'chemical/x-xyz',
+        'xz' => 'application/x-xz',
+        'yaml' => 'text/yaml',
+        'yang' => 'application/yang',
+        'yin' => 'application/yin+xml',
+        'yml' => 'text/yaml',
+        'ymp' => 'text/x-suse-ymp',
+        'z' => 'application/x-compress',
+        'z1' => 'application/x-zmachine',
+        'z2' => 'application/x-zmachine',
+        'z3' => 'application/x-zmachine',
+        'z4' => 'application/x-zmachine',
+        'z5' => 'application/x-zmachine',
+        'z6' => 'application/x-zmachine',
+        'z7' => 'application/x-zmachine',
+        'z8' => 'application/x-zmachine',
+        'zaz' => 'application/vnd.zzazz.deck+xml',
+        'zip' => 'application/zip',
+        'zir' => 'application/vnd.zul',
+        'zirz' => 'application/vnd.zul',
+        'zmm' => 'application/vnd.handheld-entertainment+xml',
+        'zsh' => 'text/x-scriptzsh',
+    ];
+
+    /**
+     * @var array<string, string>
+     *
+     * @internal
+     */
+    public const EXTENSIONS_FOR_MIME_TIMES = [
+        'application/andrew-inset' => ['ez'],
+        'application/appinstaller' => ['appinstaller'],
+        'application/applixware' => ['aw'],
+        'application/appx' => ['appx'],
+        'application/appxbundle' => ['appxbundle'],
+        'application/atom+xml' => ['atom'],
+        'application/atomcat+xml' => ['atomcat'],
+        'application/atomdeleted+xml' => ['atomdeleted'],
+        'application/atomsvc+xml' => ['atomsvc'],
+        'application/atsc-dwd+xml' => ['dwd'],
+        'application/atsc-held+xml' => ['held'],
+        'application/atsc-rsat+xml' => ['rsat'],
+        'application/automationml-aml+xml' => ['aml'],
+        'application/automationml-amlx+zip' => ['amlx'],
+        'application/bdoc' => ['bdoc'],
+        'application/calendar+xml' => ['xcs'],
+        'application/ccxml+xml' => ['ccxml'],
+        'application/cdfx+xml' => ['cdfx'],
+        'application/cdmi-capability' => ['cdmia'],
+        'application/cdmi-container' => ['cdmic'],
+        'application/cdmi-domain' => ['cdmid'],
+        'application/cdmi-object' => ['cdmio'],
+        'application/cdmi-queue' => ['cdmiq'],
+        'application/cpl+xml' => ['cpl'],
+        'application/cu-seeme' => ['cu'],
+        'application/cwl' => ['cwl'],
+        'application/dash+xml' => ['mpd'],
+        'application/dash-patch+xml' => ['mpp'],
+        'application/davmount+xml' => ['davmount'],
+        'application/docbook+xml' => ['dbk'],
+        'application/dssc+der' => ['dssc'],
+        'application/dssc+xml' => ['xdssc'],
+        'application/ecmascript' => ['ecma'],
+        'application/emma+xml' => ['emma'],
+        'application/emotionml+xml' => ['emotionml'],
+        'application/epub+zip' => ['epub'],
+        'application/exi' => ['exi'],
+        'application/express' => ['exp'],
+        'application/fdf' => ['fdf'],
+        'application/fdt+xml' => ['fdt'],
+        'application/font-tdpfr' => ['pfr'],
+        'application/geo+json' => ['geojson'],
+        'application/gml+xml' => ['gml'],
+        'application/gpx+xml' => ['gpx'],
+        'application/gxf' => ['gxf'],
+        'application/gzip' => ['gz', 'gzip'],
+        'application/hjson' => ['hjson'],
+        'application/hyperstudio' => ['stk'],
+        'application/inkml+xml' => ['ink', 'inkml'],
+        'application/ipfix' => ['ipfix'],
+        'application/its+xml' => ['its'],
+        'application/java-archive' => ['jar', 'war', 'ear'],
+        'application/java-serialized-object' => ['ser'],
+        'application/java-vm' => ['class'],
+        'application/javascript' => ['js'],
+        'application/json' => ['json', 'map'],
+        'application/json5' => ['json5'],
+        'application/jsonml+json' => ['jsonml'],
+        'application/ld+json' => ['jsonld'],
+        'application/lgr+xml' => ['lgr'],
+        'application/lost+xml' => ['lostxml'],
+        'application/mac-binhex40' => ['hqx'],
+        'application/mac-compactpro' => ['cpt'],
+        'application/mads+xml' => ['mads'],
+        'application/manifest+json' => ['webmanifest'],
+        'application/marc' => ['mrc'],
+        'application/marcxml+xml' => ['mrcx'],
+        'application/mathematica' => ['ma', 'nb', 'mb'],
+        'application/mathml+xml' => ['mathml'],
+        'application/mbox' => ['mbox'],
+        'application/media-policy-dataset+xml' => ['mpf'],
+        'application/mediaservercontrol+xml' => ['mscml'],
+        'application/metalink+xml' => ['metalink'],
+        'application/metalink4+xml' => ['meta4'],
+        'application/mets+xml' => ['mets'],
+        'application/mmt-aei+xml' => ['maei'],
+        'application/mmt-usd+xml' => ['musd'],
+        'application/mods+xml' => ['mods'],
+        'application/mp21' => ['m21', 'mp21'],
+        'application/mp4' => ['mp4', 'mpg4', 'mp4s', 'm4p'],
+        'application/msix' => ['msix'],
+        'application/msixbundle' => ['msixbundle'],
+        'application/msword' => ['doc', 'dot', 'word'],
+        'application/mxf' => ['mxf'],
+        'application/n-quads' => ['nq'],
+        'application/n-triples' => ['nt'],
+        'application/node' => ['cjs'],
+        'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy', 'exe', 'dll', 'deb', 'dmg', 'iso', 'img', 'msi', 'msp', 'msm', 'buffer', 'phar', 'lha', 'lzh', 'class', 'sea', 'dmn', 'bpmn', 'kdb', 'sst', 'csr'],
+        'application/oda' => ['oda'],
+        'application/oebps-package+xml' => ['opf'],
+        'application/ogg' => ['ogx'],
+        'application/omdoc+xml' => ['omdoc'],
+        'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'],
+        'application/oxps' => ['oxps'],
+        'application/p2p-overlay+xml' => ['relo'],
+        'application/patch-ops-error+xml' => ['xer'],
+        'application/pdf' => ['pdf', 'ai'],
+        'application/pgp-encrypted' => ['pgp'],
+        'application/pgp-keys' => ['asc'],
+        'application/pgp-signature' => ['sig', 'asc'],
+        'application/pics-rules' => ['prf'],
+        'application/pkcs10' => ['p10'],
+        'application/pkcs7-mime' => ['p7m', 'p7c'],
+        'application/pkcs7-signature' => ['p7s'],
+        'application/pkcs8' => ['p8'],
+        'application/pkix-attr-cert' => ['ac'],
+        'application/pkix-cert' => ['cer'],
+        'application/pkix-crl' => ['crl'],
+        'application/pkix-pkipath' => ['pkipath'],
+        'application/pkixcmp' => ['pki'],
+        'application/pls+xml' => ['pls'],
+        'application/postscript' => ['ai', 'eps', 'ps'],
+        'application/provenance+xml' => ['provx'],
+        'application/prs.cww' => ['cww'],
+        'application/prs.xsf+xml' => ['xsf'],
+        'application/pskc+xml' => ['pskcxml'],
+        'application/raml+yaml' => ['raml'],
+        'application/rdf+xml' => ['rdf', 'owl'],
+        'application/reginfo+xml' => ['rif'],
+        'application/relax-ng-compact-syntax' => ['rnc'],
+        'application/resource-lists+xml' => ['rl'],
+        'application/resource-lists-diff+xml' => ['rld'],
+        'application/rls-services+xml' => ['rs'],
+        'application/route-apd+xml' => ['rapd'],
+        'application/route-s-tsid+xml' => ['sls'],
+        'application/route-usd+xml' => ['rusd'],
+        'application/rpki-ghostbusters' => ['gbr'],
+        'application/rpki-manifest' => ['mft'],
+        'application/rpki-roa' => ['roa'],
+        'application/rsd+xml' => ['rsd'],
+        'application/rss+xml' => ['rss'],
+        'application/rtf' => ['rtf'],
+        'application/sbml+xml' => ['sbml'],
+        'application/scvp-cv-request' => ['scq'],
+        'application/scvp-cv-response' => ['scs'],
+        'application/scvp-vp-request' => ['spq'],
+        'application/scvp-vp-response' => ['spp'],
+        'application/sdp' => ['sdp'],
+        'application/senml+xml' => ['senmlx'],
+        'application/sensml+xml' => ['sensmlx'],
+        'application/set-payment-initiation' => ['setpay'],
+        'application/set-registration-initiation' => ['setreg'],
+        'application/shf+xml' => ['shf'],
+        'application/sieve' => ['siv', 'sieve'],
+        'application/smil+xml' => ['smi', 'smil'],
+        'application/sparql-query' => ['rq'],
+        'application/sparql-results+xml' => ['srx'],
+        'application/sql' => ['sql'],
+        'application/srgs' => ['gram'],
+        'application/srgs+xml' => ['grxml'],
+        'application/sru+xml' => ['sru'],
+        'application/ssdl+xml' => ['ssdl'],
+        'application/ssml+xml' => ['ssml'],
+        'application/swid+xml' => ['swidtag'],
+        'application/tei+xml' => ['tei', 'teicorpus'],
+        'application/thraud+xml' => ['tfi'],
+        'application/timestamped-data' => ['tsd'],
+        'application/toml' => ['toml'],
+        'application/trig' => ['trig'],
+        'application/ttml+xml' => ['ttml'],
+        'application/ubjson' => ['ubj'],
+        'application/urc-ressheet+xml' => ['rsheet'],
+        'application/urc-targetdesc+xml' => ['td'],
+        'application/vnd.1000minds.decision-model+xml' => ['1km'],
+        'application/vnd.3gpp.pic-bw-large' => ['plb'],
+        'application/vnd.3gpp.pic-bw-small' => ['psb'],
+        'application/vnd.3gpp.pic-bw-var' => ['pvb'],
+        'application/vnd.3gpp2.tcap' => ['tcap'],
+        'application/vnd.3m.post-it-notes' => ['pwn'],
+        'application/vnd.accpac.simply.aso' => ['aso'],
+        'application/vnd.accpac.simply.imp' => ['imp'],
+        'application/vnd.acucobol' => ['acu'],
+        'application/vnd.acucorp' => ['atc', 'acutc'],
+        'application/vnd.adobe.air-application-installer-package+zip' => ['air'],
+        'application/vnd.adobe.formscentral.fcdt' => ['fcdt'],
+        'application/vnd.adobe.fxp' => ['fxp', 'fxpl'],
+        'application/vnd.adobe.xdp+xml' => ['xdp'],
+        'application/vnd.adobe.xfdf' => ['xfdf'],
+        'application/vnd.age' => ['age'],
+        'application/vnd.ahead.space' => ['ahead'],
+        'application/vnd.airzip.filesecure.azf' => ['azf'],
+        'application/vnd.airzip.filesecure.azs' => ['azs'],
+        'application/vnd.amazon.ebook' => ['azw'],
+        'application/vnd.americandynamics.acc' => ['acc'],
+        'application/vnd.amiga.ami' => ['ami'],
+        'application/vnd.android.package-archive' => ['apk'],
+        'application/vnd.anser-web-certificate-issue-initiation' => ['cii'],
+        'application/vnd.anser-web-funds-transfer-initiation' => ['fti'],
+        'application/vnd.antix.game-component' => ['atx'],
+        'application/vnd.apple.installer+xml' => ['mpkg'],
+        'application/vnd.apple.keynote' => ['key'],
+        'application/vnd.apple.mpegurl' => ['m3u8'],
+        'application/vnd.apple.numbers' => ['numbers'],
+        'application/vnd.apple.pages' => ['pages'],
+        'application/vnd.apple.pkpass' => ['pkpass'],
+        'application/vnd.aristanetworks.swi' => ['swi'],
+        'application/vnd.astraea-software.iota' => ['iota'],
+        'application/vnd.audiograph' => ['aep'],
+        'application/vnd.balsamiq.bmml+xml' => ['bmml'],
+        'application/vnd.blueice.multipass' => ['mpm'],
+        'application/vnd.bmi' => ['bmi'],
+        'application/vnd.businessobjects' => ['rep'],
+        'application/vnd.chemdraw+xml' => ['cdxml'],
+        'application/vnd.chipnuts.karaoke-mmd' => ['mmd'],
+        'application/vnd.cinderella' => ['cdy'],
+        'application/vnd.citationstyles.style+xml' => ['csl'],
+        'application/vnd.claymore' => ['cla'],
+        'application/vnd.cloanto.rp9' => ['rp9'],
+        'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'],
+        'application/vnd.cluetrust.cartomobile-config' => ['c11amc'],
+        'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'],
+        'application/vnd.commonspace' => ['csp'],
+        'application/vnd.contact.cmsg' => ['cdbcmsg'],
+        'application/vnd.cosmocaller' => ['cmc'],
+        'application/vnd.crick.clicker' => ['clkx'],
+        'application/vnd.crick.clicker.keyboard' => ['clkk'],
+        'application/vnd.crick.clicker.palette' => ['clkp'],
+        'application/vnd.crick.clicker.template' => ['clkt'],
+        'application/vnd.crick.clicker.wordbank' => ['clkw'],
+        'application/vnd.criticaltools.wbs+xml' => ['wbs'],
+        'application/vnd.ctc-posml' => ['pml'],
+        'application/vnd.cups-ppd' => ['ppd'],
+        'application/vnd.curl.car' => ['car'],
+        'application/vnd.curl.pcurl' => ['pcurl'],
+        'application/vnd.dart' => ['dart'],
+        'application/vnd.data-vision.rdz' => ['rdz'],
+        'application/vnd.dbf' => ['dbf'],
+        'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'],
+        'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'],
+        'application/vnd.dece.unspecified' => ['uvx', 'uvvx'],
+        'application/vnd.dece.zip' => ['uvz', 'uvvz'],
+        'application/vnd.denovo.fcselayout-link' => ['fe_launch'],
+        'application/vnd.dna' => ['dna'],
+        'application/vnd.dolby.mlp' => ['mlp'],
+        'application/vnd.dpgraph' => ['dpg'],
+        'application/vnd.dreamfactory' => ['dfac'],
+        'application/vnd.ds-keypoint' => ['kpxx'],
+        'application/vnd.dvb.ait' => ['ait'],
+        'application/vnd.dvb.service' => ['svc'],
+        'application/vnd.dynageo' => ['geo'],
+        'application/vnd.ecowin.chart' => ['mag'],
+        'application/vnd.enliven' => ['nml'],
+        'application/vnd.epson.esf' => ['esf'],
+        'application/vnd.epson.msf' => ['msf'],
+        'application/vnd.epson.quickanime' => ['qam'],
+        'application/vnd.epson.salt' => ['slt'],
+        'application/vnd.epson.ssf' => ['ssf'],
+        'application/vnd.eszigno3+xml' => ['es3', 'et3'],
+        'application/vnd.ezpix-album' => ['ez2'],
+        'application/vnd.ezpix-package' => ['ez3'],
+        'application/vnd.fdf' => ['fdf'],
+        'application/vnd.fdsn.mseed' => ['mseed'],
+        'application/vnd.fdsn.seed' => ['seed', 'dataless'],
+        'application/vnd.flographit' => ['gph'],
+        'application/vnd.fluxtime.clip' => ['ftc'],
+        'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'],
+        'application/vnd.frogans.fnc' => ['fnc'],
+        'application/vnd.frogans.ltf' => ['ltf'],
+        'application/vnd.fsc.weblaunch' => ['fsc'],
+        'application/vnd.fujitsu.oasys' => ['oas'],
+        'application/vnd.fujitsu.oasys2' => ['oa2'],
+        'application/vnd.fujitsu.oasys3' => ['oa3'],
+        'application/vnd.fujitsu.oasysgp' => ['fg5'],
+        'application/vnd.fujitsu.oasysprs' => ['bh2'],
+        'application/vnd.fujixerox.ddd' => ['ddd'],
+        'application/vnd.fujixerox.docuworks' => ['xdw'],
+        'application/vnd.fujixerox.docuworks.binder' => ['xbd'],
+        'application/vnd.fuzzysheet' => ['fzs'],
+        'application/vnd.genomatix.tuxedo' => ['txd'],
+        'application/vnd.geogebra.file' => ['ggb'],
+        'application/vnd.geogebra.tool' => ['ggt'],
+        'application/vnd.geometry-explorer' => ['gex', 'gre'],
+        'application/vnd.geonext' => ['gxt'],
+        'application/vnd.geoplan' => ['g2w'],
+        'application/vnd.geospace' => ['g3w'],
+        'application/vnd.gmx' => ['gmx'],
+        'application/vnd.google-apps.document' => ['gdoc'],
+        'application/vnd.google-apps.presentation' => ['gslides'],
+        'application/vnd.google-apps.spreadsheet' => ['gsheet'],
+        'application/vnd.google-earth.kml+xml' => ['kml'],
+        'application/vnd.google-earth.kmz' => ['kmz'],
+        'application/vnd.grafeq' => ['gqf', 'gqs'],
+        'application/vnd.groove-account' => ['gac'],
+        'application/vnd.groove-help' => ['ghf'],
+        'application/vnd.groove-identity-message' => ['gim'],
+        'application/vnd.groove-injector' => ['grv'],
+        'application/vnd.groove-tool-message' => ['gtm'],
+        'application/vnd.groove-tool-template' => ['tpl'],
+        'application/vnd.groove-vcard' => ['vcg'],
+        'application/vnd.hal+xml' => ['hal'],
+        'application/vnd.handheld-entertainment+xml' => ['zmm'],
+        'application/vnd.hbci' => ['hbci'],
+        'application/vnd.hhe.lesson-player' => ['les'],
+        'application/vnd.hp-hpgl' => ['hpgl'],
+        'application/vnd.hp-hpid' => ['hpid'],
+        'application/vnd.hp-hps' => ['hps'],
+        'application/vnd.hp-jlyt' => ['jlt'],
+        'application/vnd.hp-pcl' => ['pcl'],
+        'application/vnd.hp-pclxl' => ['pclxl'],
+        'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'],
+        'application/vnd.ibm.minipay' => ['mpy'],
+        'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'],
+        'application/vnd.ibm.rights-management' => ['irm'],
+        'application/vnd.ibm.secure-container' => ['sc'],
+        'application/vnd.iccprofile' => ['icc', 'icm'],
+        'application/vnd.igloader' => ['igl'],
+        'application/vnd.immervision-ivp' => ['ivp'],
+        'application/vnd.immervision-ivu' => ['ivu'],
+        'application/vnd.insors.igm' => ['igm'],
+        'application/vnd.intercon.formnet' => ['xpw', 'xpx'],
+        'application/vnd.intergeo' => ['i2g'],
+        'application/vnd.intu.qbo' => ['qbo'],
+        'application/vnd.intu.qfx' => ['qfx'],
+        'application/vnd.ipunplugged.rcprofile' => ['rcprofile'],
+        'application/vnd.irepository.package+xml' => ['irp'],
+        'application/vnd.is-xpr' => ['xpr'],
+        'application/vnd.isac.fcs' => ['fcs'],
+        'application/vnd.jam' => ['jam'],
+        'application/vnd.jcp.javame.midlet-rms' => ['rms'],
+        'application/vnd.jisp' => ['jisp'],
+        'application/vnd.joost.joda-archive' => ['joda'],
+        'application/vnd.kahootz' => ['ktz', 'ktr'],
+        'application/vnd.kde.karbon' => ['karbon'],
+        'application/vnd.kde.kchart' => ['chrt'],
+        'application/vnd.kde.kformula' => ['kfo'],
+        'application/vnd.kde.kivio' => ['flw'],
+        'application/vnd.kde.kontour' => ['kon'],
+        'application/vnd.kde.kpresenter' => ['kpr', 'kpt'],
+        'application/vnd.kde.kspread' => ['ksp'],
+        'application/vnd.kde.kword' => ['kwd', 'kwt'],
+        'application/vnd.kenameaapp' => ['htke'],
+        'application/vnd.kidspiration' => ['kia'],
+        'application/vnd.kinar' => ['kne', 'knp'],
+        'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'],
+        'application/vnd.kodak-descriptor' => ['sse'],
+        'application/vnd.las.las+xml' => ['lasxml'],
+        'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'],
+        'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'],
+        'application/vnd.lotus-1-2-3' => ['123'],
+        'application/vnd.lotus-approach' => ['apr'],
+        'application/vnd.lotus-freelance' => ['pre'],
+        'application/vnd.lotus-notes' => ['nsf'],
+        'application/vnd.lotus-organizer' => ['org'],
+        'application/vnd.lotus-screencam' => ['scm'],
+        'application/vnd.lotus-wordpro' => ['lwp'],
+        'application/vnd.macports.portpkg' => ['portpkg'],
+        'application/vnd.mapbox-vector-tile' => ['mvt'],
+        'application/vnd.mcd' => ['mcd'],
+        'application/vnd.medcalcdata' => ['mc1'],
+        'application/vnd.mediastation.cdkey' => ['cdkey'],
+        'application/vnd.mfer' => ['mwf'],
+        'application/vnd.mfmp' => ['mfm'],
+        'application/vnd.micrografx.flo' => ['flo'],
+        'application/vnd.micrografx.igx' => ['igx'],
+        'application/vnd.mif' => ['mif'],
+        'application/vnd.mobius.daf' => ['daf'],
+        'application/vnd.mobius.dis' => ['dis'],
+        'application/vnd.mobius.mbk' => ['mbk'],
+        'application/vnd.mobius.mqy' => ['mqy'],
+        'application/vnd.mobius.msl' => ['msl'],
+        'application/vnd.mobius.plc' => ['plc'],
+        'application/vnd.mobius.txf' => ['txf'],
+        'application/vnd.mophun.application' => ['mpn'],
+        'application/vnd.mophun.certificate' => ['mpc'],
+        'application/vnd.mozilla.xul+xml' => ['xul'],
+        'application/vnd.ms-artgalry' => ['cil'],
+        'application/vnd.ms-cab-compressed' => ['cab'],
+        'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw'],
+        'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'],
+        'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'],
+        'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'],
+        'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'],
+        'application/vnd.ms-fontobject' => ['eot'],
+        'application/vnd.ms-htmlhelp' => ['chm'],
+        'application/vnd.ms-ims' => ['ims'],
+        'application/vnd.ms-lrm' => ['lrm'],
+        'application/vnd.ms-officetheme' => ['thmx'],
+        'application/vnd.ms-outlook' => ['msg'],
+        'application/vnd.ms-pki.seccat' => ['cat'],
+        'application/vnd.ms-pki.stl' => ['stl'],
+        'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppa'],
+        'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'],
+        'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'],
+        'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'],
+        'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'],
+        'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'],
+        'application/vnd.ms-project' => ['mpp', 'mpt'],
+        'application/vnd.ms-word.document.macroenabled.12' => ['docm'],
+        'application/vnd.ms-word.template.macroenabled.12' => ['dotm'],
+        'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb'],
+        'application/vnd.ms-wpl' => ['wpl'],
+        'application/vnd.ms-xpsdocument' => ['xps'],
+        'application/vnd.mseq' => ['mseq'],
+        'application/vnd.musician' => ['mus'],
+        'application/vnd.muvee.style' => ['msty'],
+        'application/vnd.mynfc' => ['taglet'],
+        'application/vnd.neurolanguage.nlu' => ['nlu'],
+        'application/vnd.nitf' => ['ntf', 'nitf'],
+        'application/vnd.noblenet-directory' => ['nnd'],
+        'application/vnd.noblenet-sealer' => ['nns'],
+        'application/vnd.noblenet-web' => ['nnw'],
+        'application/vnd.nokia.n-gage.ac+xml' => ['ac'],
+        'application/vnd.nokia.n-gage.data' => ['ngdat'],
+        'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'],
+        'application/vnd.nokia.radio-preset' => ['rpst'],
+        'application/vnd.nokia.radio-presets' => ['rpss'],
+        'application/vnd.novadigm.edm' => ['edm'],
+        'application/vnd.novadigm.edx' => ['edx'],
+        'application/vnd.novadigm.ext' => ['ext'],
+        'application/vnd.oasis.opendocument.chart' => ['odc'],
+        'application/vnd.oasis.opendocument.chart-template' => ['otc'],
+        'application/vnd.oasis.opendocument.database' => ['odb'],
+        'application/vnd.oasis.opendocument.formula' => ['odf'],
+        'application/vnd.oasis.opendocument.formula-template' => ['odft'],
+        'application/vnd.oasis.opendocument.graphics' => ['odg'],
+        'application/vnd.oasis.opendocument.graphics-template' => ['otg'],
+        'application/vnd.oasis.opendocument.image' => ['odi'],
+        'application/vnd.oasis.opendocument.image-template' => ['oti'],
+        'application/vnd.oasis.opendocument.presentation' => ['odp'],
+        'application/vnd.oasis.opendocument.presentation-template' => ['otp'],
+        'application/vnd.oasis.opendocument.spreadsheet' => ['ods'],
+        'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'],
+        'application/vnd.oasis.opendocument.text' => ['odt'],
+        'application/vnd.oasis.opendocument.text-master' => ['odm'],
+        'application/vnd.oasis.opendocument.text-template' => ['ott'],
+        'application/vnd.oasis.opendocument.text-web' => ['oth'],
+        'application/vnd.olpc-sugar' => ['xo'],
+        'application/vnd.oma.dd2+xml' => ['dd2'],
+        'application/vnd.openblox.game+xml' => ['obgx'],
+        'application/vnd.openofficeorg.extension' => ['oxt'],
+        'application/vnd.openstreetmap.data+xml' => ['osm'],
+        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'],
+        'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'],
+        'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'],
+        'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'],
+        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'],
+        'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'],
+        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'],
+        'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'],
+        'application/vnd.osgeo.mapguide.package' => ['mgp'],
+        'application/vnd.osgi.dp' => ['dp'],
+        'application/vnd.osgi.subsystem' => ['esa'],
+        'application/vnd.palm' => ['pdb', 'pqa', 'oprc'],
+        'application/vnd.pawaafile' => ['paw'],
+        'application/vnd.pg.format' => ['str'],
+        'application/vnd.pg.osasli' => ['ei6'],
+        'application/vnd.picsel' => ['efif'],
+        'application/vnd.pmi.widget' => ['wg'],
+        'application/vnd.pocketlearn' => ['plf'],
+        'application/vnd.powerbuilder6' => ['pbd'],
+        'application/vnd.previewsystems.box' => ['box'],
+        'application/vnd.proteus.magazine' => ['mgz'],
+        'application/vnd.publishare-delta-tree' => ['qps'],
+        'application/vnd.pvi.ptid1' => ['ptid'],
+        'application/vnd.pwg-xhtml-print+xml' => ['xhtm'],
+        'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'],
+        'application/vnd.rar' => ['rar'],
+        'application/vnd.realvnc.bed' => ['bed'],
+        'application/vnd.recordare.musicxml' => ['mxl'],
+        'application/vnd.recordare.musicxml+xml' => ['musicxml'],
+        'application/vnd.rig.cryptonote' => ['cryptonote'],
+        'application/vnd.rim.cod' => ['cod'],
+        'application/vnd.rn-realmedia' => ['rm'],
+        'application/vnd.rn-realmedia-vbr' => ['rmvb'],
+        'application/vnd.route66.link66+xml' => ['link66'],
+        'application/vnd.sailingtracker.track' => ['st'],
+        'application/vnd.seemail' => ['see'],
+        'application/vnd.sema' => ['sema'],
+        'application/vnd.semd' => ['semd'],
+        'application/vnd.semf' => ['semf'],
+        'application/vnd.shana.informed.formdata' => ['ifm'],
+        'application/vnd.shana.informed.formtemplate' => ['itp'],
+        'application/vnd.shana.informed.interchange' => ['iif'],
+        'application/vnd.shana.informed.package' => ['ipk'],
+        'application/vnd.simtech-mindmapper' => ['twd', 'twds'],
+        'application/vnd.smaf' => ['mmf'],
+        'application/vnd.smart.teacher' => ['teacher'],
+        'application/vnd.software602.filler.form+xml' => ['fo'],
+        'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'],
+        'application/vnd.spotfire.dxp' => ['dxp'],
+        'application/vnd.spotfire.sfs' => ['sfs'],
+        'application/vnd.stardivision.calc' => ['sdc'],
+        'application/vnd.stardivision.draw' => ['sda'],
+        'application/vnd.stardivision.impress' => ['sdd'],
+        'application/vnd.stardivision.math' => ['smf'],
+        'application/vnd.stardivision.writer' => ['sdw', 'vor'],
+        'application/vnd.stardivision.writer-global' => ['sgl'],
+        'application/vnd.stepmania.package' => ['smzip'],
+        'application/vnd.stepmania.stepchart' => ['sm'],
+        'application/vnd.sun.wadl+xml' => ['wadl'],
+        'application/vnd.sun.xml.calc' => ['sxc'],
+        'application/vnd.sun.xml.calc.template' => ['stc'],
+        'application/vnd.sun.xml.draw' => ['sxd'],
+        'application/vnd.sun.xml.draw.template' => ['std'],
+        'application/vnd.sun.xml.impress' => ['sxi'],
+        'application/vnd.sun.xml.impress.template' => ['sti'],
+        'application/vnd.sun.xml.math' => ['sxm'],
+        'application/vnd.sun.xml.writer' => ['sxw'],
+        'application/vnd.sun.xml.writer.global' => ['sxg'],
+        'application/vnd.sun.xml.writer.template' => ['stw'],
+        'application/vnd.sus-calendar' => ['sus', 'susp'],
+        'application/vnd.svd' => ['svd'],
+        'application/vnd.symbian.install' => ['sis', 'sisx'],
+        'application/vnd.syncml+xml' => ['xsm'],
+        'application/vnd.syncml.dm+wbxml' => ['bdm'],
+        'application/vnd.syncml.dm+xml' => ['xdm'],
+        'application/vnd.syncml.dmddf+xml' => ['ddf'],
+        'application/vnd.tao.intent-module-archive' => ['tao'],
+        'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'],
+        'application/vnd.tmobile-livetv' => ['tmo'],
+        'application/vnd.trid.tpt' => ['tpt'],
+        'application/vnd.triscape.mxs' => ['mxs'],
+        'application/vnd.trueapp' => ['tra'],
+        'application/vnd.ufdl' => ['ufd', 'ufdl'],
+        'application/vnd.uiq.theme' => ['utz'],
+        'application/vnd.umajin' => ['umj'],
+        'application/vnd.unity' => ['unityweb'],
+        'application/vnd.uoml+xml' => ['uoml', 'uo'],
+        'application/vnd.vcx' => ['vcx'],
+        'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'],
+        'application/vnd.visionary' => ['vis'],
+        'application/vnd.vsf' => ['vsf'],
+        'application/vnd.wap.wbxml' => ['wbxml'],
+        'application/vnd.wap.wmlc' => ['wmlc'],
+        'application/vnd.wap.wmlscriptc' => ['wmlsc'],
+        'application/vnd.webturbo' => ['wtb'],
+        'application/vnd.wolfram.player' => ['nbp'],
+        'application/vnd.wordperfect' => ['wpd'],
+        'application/vnd.wqd' => ['wqd'],
+        'application/vnd.wt.stf' => ['stf'],
+        'application/vnd.xara' => ['xar'],
+        'application/vnd.xfdl' => ['xfdl'],
+        'application/vnd.yamaha.hv-dic' => ['hvd'],
+        'application/vnd.yamaha.hv-script' => ['hvs'],
+        'application/vnd.yamaha.hv-voice' => ['hvp'],
+        'application/vnd.yamaha.openscoreformat' => ['osf'],
+        'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'],
+        'application/vnd.yamaha.smaf-audio' => ['saf'],
+        'application/vnd.yamaha.smaf-phrase' => ['spf'],
+        'application/vnd.yellowriver-custom-menu' => ['cmp'],
+        'application/vnd.zul' => ['zir', 'zirz'],
+        'application/vnd.zzazz.deck+xml' => ['zaz'],
+        'application/voicexml+xml' => ['vxml'],
+        'application/wasm' => ['wasm'],
+        'application/watcherinfo+xml' => ['wif'],
+        'application/widget' => ['wgt'],
+        'application/winhlp' => ['hlp'],
+        'application/wsdl+xml' => ['wsdl'],
+        'application/wspolicy+xml' => ['wspolicy'],
+        'application/x-7z-compressed' => ['7z', '7zip'],
+        'application/x-abiword' => ['abw'],
+        'application/x-ace-compressed' => ['ace'],
+        'application/x-apple-diskimage' => ['dmg'],
+        'application/x-arj' => ['arj'],
+        'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'],
+        'application/x-authorware-map' => ['aam'],
+        'application/x-authorware-seg' => ['aas'],
+        'application/x-bcpio' => ['bcpio'],
+        'application/x-bdoc' => ['bdoc'],
+        'application/x-bittorrent' => ['torrent'],
+        'application/x-blorb' => ['blb', 'blorb'],
+        'application/x-bzip' => ['bz'],
+        'application/x-bzip2' => ['bz2', 'boz'],
+        'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'],
+        'application/x-cdlink' => ['vcd'],
+        'application/x-cfs-compressed' => ['cfs'],
+        'application/x-chat' => ['chat'],
+        'application/x-chess-pgn' => ['pgn'],
+        'application/x-chrome-extension' => ['crx'],
+        'application/x-cocoa' => ['cco'],
+        'application/x-conference' => ['nsc'],
+        'application/x-cpio' => ['cpio'],
+        'application/x-csh' => ['csh'],
+        'application/x-debian-package' => ['deb', 'udeb'],
+        'application/x-dgc-compressed' => ['dgc'],
+        'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'],
+        'application/x-doom' => ['wad'],
+        'application/x-dtbncx+xml' => ['ncx'],
+        'application/x-dtbook+xml' => ['dtb'],
+        'application/x-dtbresource+xml' => ['res'],
+        'application/x-dvi' => ['dvi'],
+        'application/x-envoy' => ['evy'],
+        'application/x-eva' => ['eva'],
+        'application/x-font-bdf' => ['bdf'],
+        'application/x-font-ghostscript' => ['gsf'],
+        'application/x-font-linux-psf' => ['psf'],
+        'application/x-font-pcf' => ['pcf'],
+        'application/x-font-snf' => ['snf'],
+        'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm'],
+        'application/x-freearc' => ['arc'],
+        'application/x-futuresplash' => ['spl'],
+        'application/x-gca-compressed' => ['gca'],
+        'application/x-glulx' => ['ulx'],
+        'application/x-gnumeric' => ['gnumeric'],
+        'application/x-gramps-xml' => ['gramps'],
+        'application/x-gtar' => ['gtar'],
+        'application/x-hdf' => ['hdf'],
+        'application/x-httpd-php' => ['php', 'php4', 'php3', 'phtml'],
+        'application/x-install-instructions' => ['install'],
+        'application/x-iso9660-image' => ['iso'],
+        'application/x-iwork-keynote-sffkey' => ['key'],
+        'application/x-iwork-numbers-sffnumbers' => ['numbers'],
+        'application/x-iwork-pages-sffpages' => ['pages'],
+        'application/x-java-archive-diff' => ['jardiff'],
+        'application/x-java-jnlp-file' => ['jnlp'],
+        'application/x-keepass2' => ['kdbx'],
+        'application/x-latex' => ['latex'],
+        'application/x-lua-bytecode' => ['luac'],
+        'application/x-lzh-compressed' => ['lzh', 'lha'],
+        'application/x-makeself' => ['run'],
+        'application/x-mie' => ['mie'],
+        'application/x-mobipocket-ebook' => ['prc', 'mobi'],
+        'application/x-ms-application' => ['application'],
+        'application/x-ms-shortcut' => ['lnk'],
+        'application/x-ms-wmd' => ['wmd'],
+        'application/x-ms-wmz' => ['wmz'],
+        'application/x-ms-xbap' => ['xbap'],
+        'application/x-msaccess' => ['mdb'],
+        'application/x-msbinder' => ['obd'],
+        'application/x-mscardfile' => ['crd'],
+        'application/x-msclip' => ['clp'],
+        'application/x-msdos-program' => ['exe'],
+        'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'],
+        'application/x-msmediaview' => ['mvb', 'm13', 'm14'],
+        'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'],
+        'application/x-msmoney' => ['mny'],
+        'application/x-mspublisher' => ['pub'],
+        'application/x-msschedule' => ['scd'],
+        'application/x-msterminal' => ['trm'],
+        'application/x-mswrite' => ['wri'],
+        'application/x-netcdf' => ['nc', 'cdf'],
+        'application/x-ns-proxy-autoconfig' => ['pac'],
+        'application/x-nzb' => ['nzb'],
+        'application/x-perl' => ['pl', 'pm'],
+        'application/x-pilot' => ['prc', 'pdb'],
+        'application/x-pkcs12' => ['p12', 'pfx'],
+        'application/x-pkcs7-certificates' => ['p7b', 'spc'],
+        'application/x-pkcs7-certreqresp' => ['p7r'],
+        'application/x-rar-compressed' => ['rar'],
+        'application/x-redhat-package-manager' => ['rpm'],
+        'application/x-research-info-systems' => ['ris'],
+        'application/x-sea' => ['sea'],
+        'application/x-sh' => ['sh'],
+        'application/x-shar' => ['shar'],
+        'application/x-shockwave-flash' => ['swf'],
+        'application/x-silverlight-app' => ['xap'],
+        'application/x-sql' => ['sql'],
+        'application/x-stuffit' => ['sit'],
+        'application/x-stuffitx' => ['sitx'],
+        'application/x-subrip' => ['srt'],
+        'application/x-sv4cpio' => ['sv4cpio'],
+        'application/x-sv4crc' => ['sv4crc'],
+        'application/x-t3vm-image' => ['t3'],
+        'application/x-tads' => ['gam'],
+        'application/x-tar' => ['tar', 'tgz'],
+        'application/x-tcl' => ['tcl', 'tk'],
+        'application/x-tex' => ['tex'],
+        'application/x-tex-tfm' => ['tfm'],
+        'application/x-texinfo' => ['texinfo', 'texi'],
+        'application/x-tgif' => ['obj'],
+        'application/x-ustar' => ['ustar'],
+        'application/x-virtualbox-hdd' => ['hdd'],
+        'application/x-virtualbox-ova' => ['ova'],
+        'application/x-virtualbox-ovf' => ['ovf'],
+        'application/x-virtualbox-vbox' => ['vbox'],
+        'application/x-virtualbox-vbox-extpack' => ['vbox-extpack'],
+        'application/x-virtualbox-vdi' => ['vdi'],
+        'application/x-virtualbox-vhd' => ['vhd'],
+        'application/x-virtualbox-vmdk' => ['vmdk'],
+        'application/x-wais-source' => ['src'],
+        'application/x-web-app-manifest+json' => ['webapp'],
+        'application/x-x509-ca-cert' => ['der', 'crt', 'pem'],
+        'application/x-xfig' => ['fig'],
+        'application/x-xliff+xml' => ['xlf'],
+        'application/x-xpinstall' => ['xpi'],
+        'application/x-xz' => ['xz'],
+        'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'],
+        'application/xaml+xml' => ['xaml'],
+        'application/xcap-att+xml' => ['xav'],
+        'application/xcap-caps+xml' => ['xca'],
+        'application/xcap-diff+xml' => ['xdf'],
+        'application/xcap-el+xml' => ['xel'],
+        'application/xcap-ns+xml' => ['xns'],
+        'application/xenc+xml' => ['xenc'],
+        'application/xfdf' => ['xfdf'],
+        'application/xhtml+xml' => ['xhtml', 'xht'],
+        'application/xliff+xml' => ['xlf'],
+        'application/xml' => ['xml', 'xsl', 'xsd', 'rng'],
+        'application/xml-dtd' => ['dtd'],
+        'application/xop+xml' => ['xop'],
+        'application/xproc+xml' => ['xpl'],
+        'application/xslt+xml' => ['xsl', 'xslt'],
+        'application/xspf+xml' => ['xspf'],
+        'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'],
+        'application/yang' => ['yang'],
+        'application/yin+xml' => ['yin'],
+        'application/zip' => ['zip'],
+        'audio/3gpp' => ['3gpp'],
+        'audio/aac' => ['adts', 'aac'],
+        'audio/adpcm' => ['adp'],
+        'audio/amr' => ['amr'],
+        'audio/basic' => ['au', 'snd'],
+        'audio/midi' => ['mid', 'midi', 'kar', 'rmi'],
+        'audio/mobile-xmf' => ['mxmf'],
+        'audio/mp3' => ['mp3'],
+        'audio/mp4' => ['m4a', 'mp4a'],
+        'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'],
+        'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'],
+        'audio/s3m' => ['s3m'],
+        'audio/silk' => ['sil'],
+        'audio/vnd.dece.audio' => ['uva', 'uvva'],
+        'audio/vnd.digital-winds' => ['eol'],
+        'audio/vnd.dra' => ['dra'],
+        'audio/vnd.dts' => ['dts'],
+        'audio/vnd.dts.hd' => ['dtshd'],
+        'audio/vnd.lucent.voice' => ['lvp'],
+        'audio/vnd.ms-playready.media.pya' => ['pya'],
+        'audio/vnd.nuera.ecelp4800' => ['ecelp4800'],
+        'audio/vnd.nuera.ecelp7470' => ['ecelp7470'],
+        'audio/vnd.nuera.ecelp9600' => ['ecelp9600'],
+        'audio/vnd.rip' => ['rip'],
+        'audio/wav' => ['wav'],
+        'audio/wave' => ['wav'],
+        'audio/webm' => ['weba'],
+        'audio/x-aac' => ['aac'],
+        'audio/x-aiff' => ['aif', 'aiff', 'aifc'],
+        'audio/x-caf' => ['caf'],
+        'audio/x-flac' => ['flac'],
+        'audio/x-m4a' => ['m4a'],
+        'audio/x-matroska' => ['mka'],
+        'audio/x-mpegurl' => ['m3u'],
+        'audio/x-ms-wax' => ['wax'],
+        'audio/x-ms-wma' => ['wma'],
+        'audio/x-pn-realaudio' => ['ram', 'ra', 'rm'],
+        'audio/x-pn-realaudio-plugin' => ['rmp', 'rpm'],
+        'audio/x-realaudio' => ['ra'],
+        'audio/x-wav' => ['wav'],
+        'audio/xm' => ['xm'],
+        'chemical/x-cdx' => ['cdx'],
+        'chemical/x-cif' => ['cif'],
+        'chemical/x-cmdf' => ['cmdf'],
+        'chemical/x-cml' => ['cml'],
+        'chemical/x-csml' => ['csml'],
+        'chemical/x-xyz' => ['xyz'],
+        'font/collection' => ['ttc'],
+        'font/otf' => ['otf'],
+        'font/ttf' => ['ttf'],
+        'font/woff' => ['woff'],
+        'font/woff2' => ['woff2'],
+        'image/aces' => ['exr'],
+        'image/apng' => ['apng'],
+        'image/avci' => ['avci'],
+        'image/avcs' => ['avcs'],
+        'image/avif' => ['avif'],
+        'image/bmp' => ['bmp', 'dib'],
+        'image/cgm' => ['cgm'],
+        'image/dicom-rle' => ['drle'],
+        'image/dpx' => ['dpx'],
+        'image/emf' => ['emf'],
+        'image/fits' => ['fits'],
+        'image/g3fax' => ['g3'],
+        'image/gif' => ['gif'],
+        'image/heic' => ['heic'],
+        'image/heic-sequence' => ['heics'],
+        'image/heif' => ['heif'],
+        'image/heif-sequence' => ['heifs'],
+        'image/hej2k' => ['hej2'],
+        'image/hsj2' => ['hsj2'],
+        'image/ief' => ['ief'],
+        'image/jls' => ['jls'],
+        'image/jp2' => ['jp2', 'jpg2'],
+        'image/jpeg' => ['jpeg', 'jpg', 'jpe'],
+        'image/jph' => ['jph'],
+        'image/jphc' => ['jhc'],
+        'image/jpm' => ['jpm', 'jpgm'],
+        'image/jpx' => ['jpx', 'jpf'],
+        'image/jxr' => ['jxr'],
+        'image/jxra' => ['jxra'],
+        'image/jxrs' => ['jxrs'],
+        'image/jxs' => ['jxs'],
+        'image/jxsc' => ['jxsc'],
+        'image/jxsi' => ['jxsi'],
+        'image/jxss' => ['jxss'],
+        'image/ktx' => ['ktx'],
+        'image/ktx2' => ['ktx2'],
+        'image/png' => ['png'],
+        'image/prs.btif' => ['btif', 'btf'],
+        'image/prs.pti' => ['pti'],
+        'image/sgi' => ['sgi'],
+        'image/svg+xml' => ['svg', 'svgz'],
+        'image/t38' => ['t38'],
+        'image/tiff' => ['tif', 'tiff'],
+        'image/tiff-fx' => ['tfx'],
+        'image/vnd.adobe.photoshop' => ['psd'],
+        'image/vnd.airzip.accelerator.azv' => ['azv'],
+        'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'],
+        'image/vnd.djvu' => ['djvu', 'djv'],
+        'image/vnd.dvb.subtitle' => ['sub'],
+        'image/vnd.dwg' => ['dwg'],
+        'image/vnd.dxf' => ['dxf'],
+        'image/vnd.fastbidsheet' => ['fbs'],
+        'image/vnd.fpx' => ['fpx'],
+        'image/vnd.fst' => ['fst'],
+        'image/vnd.fujixerox.edmics-mmr' => ['mmr'],
+        'image/vnd.fujixerox.edmics-rlc' => ['rlc'],
+        'image/vnd.microsoft.icon' => ['ico'],
+        'image/vnd.ms-dds' => ['dds'],
+        'image/vnd.ms-modi' => ['mdi'],
+        'image/vnd.ms-photo' => ['wdp'],
+        'image/vnd.net-fpx' => ['npx'],
+        'image/vnd.pco.b16' => ['b16'],
+        'image/vnd.tencent.tap' => ['tap'],
+        'image/vnd.valve.source.texture' => ['vtf'],
+        'image/vnd.wap.wbmp' => ['wbmp'],
+        'image/vnd.xiff' => ['xif'],
+        'image/vnd.zbrush.pcx' => ['pcx'],
+        'image/webp' => ['webp'],
+        'image/wmf' => ['wmf'],
+        'image/x-3ds' => ['3ds'],
+        'image/x-cmu-raster' => ['ras'],
+        'image/x-cmx' => ['cmx'],
+        'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'],
+        'image/x-icon' => ['ico'],
+        'image/x-jng' => ['jng'],
+        'image/x-mrsid-image' => ['sid'],
+        'image/x-ms-bmp' => ['bmp'],
+        'image/x-pcx' => ['pcx'],
+        'image/x-pict' => ['pic', 'pct'],
+        'image/x-portable-anymap' => ['pnm'],
+        'image/x-portable-bitmap' => ['pbm'],
+        'image/x-portable-graymap' => ['pgm'],
+        'image/x-portable-pixmap' => ['ppm'],
+        'image/x-rgb' => ['rgb'],
+        'image/x-tga' => ['tga'],
+        'image/x-xbitmap' => ['xbm'],
+        'image/x-xpixmap' => ['xpm'],
+        'image/x-xwindowdump' => ['xwd'],
+        'message/disposition-notification' => ['disposition-notification'],
+        'message/global' => ['u8msg'],
+        'message/global-delivery-status' => ['u8dsn'],
+        'message/global-disposition-notification' => ['u8mdn'],
+        'message/global-headers' => ['u8hdr'],
+        'message/rfc822' => ['eml', 'mime'],
+        'message/vnd.wfa.wsc' => ['wsc'],
+        'model/3mf' => ['3mf'],
+        'model/gltf+json' => ['gltf'],
+        'model/gltf-binary' => ['glb'],
+        'model/iges' => ['igs', 'iges'],
+        'model/jt' => ['jt'],
+        'model/mesh' => ['msh', 'mesh', 'silo'],
+        'model/mtl' => ['mtl'],
+        'model/obj' => ['obj'],
+        'model/prc' => ['prc'],
+        'model/step+xml' => ['stpx'],
+        'model/step+zip' => ['stpz'],
+        'model/step-xml+zip' => ['stpxz'],
+        'model/stl' => ['stl'],
+        'model/u3d' => ['u3d'],
+        'model/vnd.cld' => ['cld'],
+        'model/vnd.collada+xml' => ['dae'],
+        'model/vnd.dwf' => ['dwf'],
+        'model/vnd.gdl' => ['gdl'],
+        'model/vnd.gtw' => ['gtw'],
+        'model/vnd.mts' => ['mts'],
+        'model/vnd.opengex' => ['ogex'],
+        'model/vnd.parasolid.transmit.binary' => ['x_b'],
+        'model/vnd.parasolid.transmit.text' => ['x_t'],
+        'model/vnd.pytha.pyox' => ['pyo', 'pyox'],
+        'model/vnd.sap.vds' => ['vds'],
+        'model/vnd.usda' => ['usda'],
+        'model/vnd.usdz+zip' => ['usdz'],
+        'model/vnd.valve.source.compiled-map' => ['bsp'],
+        'model/vnd.vtu' => ['vtu'],
+        'model/vrml' => ['wrl', 'vrml'],
+        'model/x3d+binary' => ['x3db', 'x3dbz'],
+        'model/x3d+fastinfoset' => ['x3db'],
+        'model/x3d+vrml' => ['x3dv', 'x3dvz'],
+        'model/x3d+xml' => ['x3d', 'x3dz'],
+        'model/x3d-vrml' => ['x3dv'],
+        'text/cache-manifest' => ['appcache', 'manifest'],
+        'text/calendar' => ['ics', 'ifb'],
+        'text/coffeescript' => ['coffee', 'litcoffee'],
+        'text/css' => ['css'],
+        'text/csv' => ['csv'],
+        'text/html' => ['html', 'htm', 'shtml'],
+        'text/jade' => ['jade'],
+        'text/javascript' => ['js', 'mjs'],
+        'text/jsx' => ['jsx'],
+        'text/less' => ['less'],
+        'text/markdown' => ['md', 'markdown'],
+        'text/mathml' => ['mml'],
+        'text/mdx' => ['mdx'],
+        'text/n3' => ['n3'],
+        'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini', 'm3u'],
+        'text/prs.lines.tag' => ['dsc'],
+        'text/richtext' => ['rtx'],
+        'text/rtf' => ['rtf'],
+        'text/sgml' => ['sgml', 'sgm'],
+        'text/shex' => ['shex'],
+        'text/slim' => ['slim', 'slm'],
+        'text/spdx' => ['spdx'],
+        'text/stylus' => ['stylus', 'styl'],
+        'text/tab-separated-values' => ['tsv'],
+        'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'],
+        'text/turtle' => ['ttl'],
+        'text/uri-list' => ['uri', 'uris', 'urls'],
+        'text/vcard' => ['vcard'],
+        'text/vnd.curl' => ['curl'],
+        'text/vnd.curl.dcurl' => ['dcurl'],
+        'text/vnd.curl.mcurl' => ['mcurl'],
+        'text/vnd.curl.scurl' => ['scurl'],
+        'text/vnd.dvb.subtitle' => ['sub'],
+        'text/vnd.familysearch.gedcom' => ['ged'],
+        'text/vnd.fly' => ['fly'],
+        'text/vnd.fmi.flexstor' => ['flx'],
+        'text/vnd.graphviz' => ['gv'],
+        'text/vnd.in3d.3dml' => ['3dml'],
+        'text/vnd.in3d.spot' => ['spot'],
+        'text/vnd.sun.j2me.app-descriptor' => ['jad'],
+        'text/vnd.wap.wml' => ['wml'],
+        'text/vnd.wap.wmlscript' => ['wmls'],
+        'text/vtt' => ['vtt'],
+        'text/wgsl' => ['wgsl'],
+        'text/x-asm' => ['s', 'asm'],
+        'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'],
+        'text/x-component' => ['htc'],
+        'text/x-fortran' => ['f', 'for', 'f77', 'f90'],
+        'text/x-handlebars-template' => ['hbs'],
+        'text/x-java-source' => ['java'],
+        'text/x-lua' => ['lua'],
+        'text/x-markdown' => ['mkd'],
+        'text/x-nfo' => ['nfo'],
+        'text/x-opml' => ['opml'],
+        'text/x-org' => ['org'],
+        'text/x-pascal' => ['p', 'pas'],
+        'text/x-processing' => ['pde'],
+        'text/x-sass' => ['sass'],
+        'text/x-scss' => ['scss'],
+        'text/x-setext' => ['etx'],
+        'text/x-sfv' => ['sfv'],
+        'text/x-suse-ymp' => ['ymp'],
+        'text/x-uuencode' => ['uu'],
+        'text/x-vcalendar' => ['vcs'],
+        'text/x-vcard' => ['vcf'],
+        'text/xml' => ['xml'],
+        'text/yaml' => ['yaml', 'yml'],
+        'video/3gpp' => ['3gp', '3gpp'],
+        'video/3gpp2' => ['3g2'],
+        'video/h261' => ['h261'],
+        'video/h263' => ['h263'],
+        'video/h264' => ['h264'],
+        'video/iso.segment' => ['m4s'],
+        'video/jpeg' => ['jpgv'],
+        'video/jpm' => ['jpm', 'jpgm'],
+        'video/mj2' => ['mj2', 'mjp2'],
+        'video/mp2t' => ['ts'],
+        'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'f4v'],
+        'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'],
+        'video/ogg' => ['ogv'],
+        'video/quicktime' => ['qt', 'mov'],
+        'video/vnd.dece.hd' => ['uvh', 'uvvh'],
+        'video/vnd.dece.mobile' => ['uvm', 'uvvm'],
+        'video/vnd.dece.pd' => ['uvp', 'uvvp'],
+        'video/vnd.dece.sd' => ['uvs', 'uvvs'],
+        'video/vnd.dece.video' => ['uvv', 'uvvv'],
+        'video/vnd.dvb.file' => ['dvb'],
+        'video/vnd.fvt' => ['fvt'],
+        'video/vnd.mpegurl' => ['mxu', 'm4u'],
+        'video/vnd.ms-playready.media.pyv' => ['pyv'],
+        'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'],
+        'video/vnd.vivo' => ['viv'],
+        'video/webm' => ['webm'],
+        'video/x-f4v' => ['f4v'],
+        'video/x-fli' => ['fli'],
+        'video/x-flv' => ['flv'],
+        'video/x-m4v' => ['m4v'],
+        'video/x-matroska' => ['mkv', 'mk3d', 'mks'],
+        'video/x-mng' => ['mng'],
+        'video/x-ms-asf' => ['asf', 'asx'],
+        'video/x-ms-vob' => ['vob'],
+        'video/x-ms-wm' => ['wm'],
+        'video/x-ms-wmv' => ['wmv'],
+        'video/x-ms-wmx' => ['wmx'],
+        'video/x-ms-wvx' => ['wvx'],
+        'video/x-msvideo' => ['avi'],
+        'video/x-sgi-movie' => ['movie'],
+        'video/x-smv' => ['smv'],
+        'x-conference/x-cooltalk' => ['ice'],
+        'application/x-photoshop' => ['psd'],
+        'application/smil' => ['smi', 'smil'],
+        'application/powerpoint' => ['ppt'],
+        'application/vnd.ms-powerpoint.addin.macroEnabled.12' => ['ppam'],
+        'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => ['pptm', 'potm'],
+        'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => ['ppsm'],
+        'application/wbxml' => ['wbxml'],
+        'application/wmlc' => ['wmlc'],
+        'application/x-httpd-php-source' => ['phps'],
+        'application/x-compress' => ['z'],
+        'application/x-rar' => ['rar'],
+        'video/vnd.rn-realvideo' => ['rv'],
+        'application/vnd.ms-word.template.macroEnabled.12' => ['docm', 'dotm'],
+        'application/vnd.ms-excel.sheet.macroEnabled.12' => ['xlsm'],
+        'application/vnd.ms-excel.template.macroEnabled.12' => ['xltm'],
+        'application/vnd.ms-excel.addin.macroEnabled.12' => ['xlam'],
+        'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => ['xlsb'],
+        'application/excel' => ['xl'],
+        'application/x-x509-user-cert' => ['pem'],
+        'application/x-pkcs10' => ['p10'],
+        'application/x-pkcs7-signature' => ['p7a'],
+        'application/pgp' => ['pgp'],
+        'application/gpg-keys' => ['gpg'],
+        'application/x-pkcs7' => ['rsa'],
+        'video/3gp' => ['3gp'],
+        'audio/acc' => ['aac'],
+        'application/vnd.mpegurl' => ['m4u'],
+        'application/videolan' => ['vlc'],
+        'audio/x-au' => ['au'],
+        'audio/ac3' => ['ac3'],
+        'text/x-scriptzsh' => ['zsh'],
+        'application/cdr' => ['cdr'],
+        'application/STEP' => ['step', 'stp'],
+    ];
+
+    public function lookupMimeType(string $extension): ?string
+    {
+        return self::MIME_TYPES_FOR_EXTENSIONS[$extension] ?? null;
+    }
+
+    public function lookupExtension(string $mimetype): ?string
+    {
+        return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype][0] ?? null;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function lookupAllExtensions(string $mimetype): array
+    {
+        return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype] ?? [];
+    }
+}
diff --git a/vendor/league/mime-type-detection/src/MimeTypeDetector.php b/vendor/league/mime-type-detection/src/MimeTypeDetector.php
new file mode 100644
index 000000000..5d799d2a8
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/MimeTypeDetector.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace League\MimeTypeDetection;
+
+interface MimeTypeDetector
+{
+    /**
+     * @param string|resource $contents
+     */
+    public function detectMimeType(string $path, $contents): ?string;
+
+    public function detectMimeTypeFromBuffer(string $contents): ?string;
+
+    public function detectMimeTypeFromPath(string $path): ?string;
+
+    public function detectMimeTypeFromFile(string $path): ?string;
+}
diff --git a/vendor/league/mime-type-detection/src/OverridingExtensionToMimeTypeMap.php b/vendor/league/mime-type-detection/src/OverridingExtensionToMimeTypeMap.php
new file mode 100644
index 000000000..0c71e4d51
--- /dev/null
+++ b/vendor/league/mime-type-detection/src/OverridingExtensionToMimeTypeMap.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace League\MimeTypeDetection;
+
+class OverridingExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
+{
+    /**
+     * @var ExtensionToMimeTypeMap
+     */
+    private $innerMap;
+
+    /**
+     * @var string[]
+     */
+    private $overrides;
+
+    /**
+     * @param array<string, string>  $overrides
+     */
+    public function __construct(ExtensionToMimeTypeMap $innerMap, array $overrides)
+    {
+        $this->innerMap = $innerMap;
+        $this->overrides = $overrides;
+    }
+
+    public function lookupMimeType(string $extension): ?string
+    {
+        return $this->overrides[$extension] ?? $this->innerMap->lookupMimeType($extension);
+    }
+}
diff --git a/vendor/services.php b/vendor/services.php
index 439648f58..565e9e7bb 100644
--- a/vendor/services.php
+++ b/vendor/services.php
@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2023-10-09 22:37:30
+// This file is automatically generated at:2023-10-10 10:15:01
 declare (strict_types = 1);
 return array (
   0 => 'think\\app\\Service',
diff --git a/vendor/topthink/think-filesystem/.gitignore b/vendor/topthink/think-filesystem/.gitignore
new file mode 100644
index 000000000..25ad74d67
--- /dev/null
+++ b/vendor/topthink/think-filesystem/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+/.idea
+/vendor
diff --git a/vendor/topthink/think-filesystem/README.md b/vendor/topthink/think-filesystem/README.md
new file mode 100644
index 000000000..90977dd7d
--- /dev/null
+++ b/vendor/topthink/think-filesystem/README.md
@@ -0,0 +1,5 @@
+# think-filesystem for ThinkPHP6.1
+
+## 安装
+
+> composer require topthink/think-filesystem
diff --git a/vendor/topthink/think-filesystem/composer.json b/vendor/topthink/think-filesystem/composer.json
new file mode 100644
index 000000000..8c4f508fb
--- /dev/null
+++ b/vendor/topthink/think-filesystem/composer.json
@@ -0,0 +1,33 @@
+{
+    "name": "topthink/think-filesystem",
+    "description": "The ThinkPHP6.1 Filesystem Package",
+    "type": "library",
+    "license": "Apache-2.0",
+    "authors": [
+        {
+            "name": "yunwuxin",
+            "email": "448901948@qq.com"
+        }
+    ],
+    "autoload": {
+        "psr-4": {
+            "think\\": "src"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "think\\tests\\": "tests/"
+        }
+    },
+    "require": {
+        "topthink/framework": "^6.1|^8.0",
+        "league/flysystem": "^2.0"
+    },
+    "require-dev": {
+        "mikey179/vfsstream": "^1.6",
+        "mockery/mockery": "^1.2",
+        "phpunit/phpunit": "^8.0"
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true
+}
diff --git a/vendor/topthink/think-filesystem/phpunit.xml.dist b/vendor/topthink/think-filesystem/phpunit.xml.dist
new file mode 100644
index 000000000..e20a13381
--- /dev/null
+++ b/vendor/topthink/think-filesystem/phpunit.xml.dist
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         beStrictAboutTestsThatDoNotTestAnything="false"
+         bootstrap="tests/bootstrap.php"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnError="false"
+         stopOnFailure="false"
+         verbose="true"
+>
+    <testsuites>
+        <testsuite name="ThinkPHP Test Suite">
+            <directory suffix="Test.php">./tests</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">./src/think</directory>
+        </whitelist>
+    </filter>
+</phpunit>
diff --git a/vendor/topthink/think-filesystem/src/Filesystem.php b/vendor/topthink/think-filesystem/src/Filesystem.php
new file mode 100644
index 000000000..0aee929f5
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/Filesystem.php
@@ -0,0 +1,89 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think;
+
+use InvalidArgumentException;
+use think\filesystem\Driver;
+use think\filesystem\driver\Local;
+use think\helper\Arr;
+
+/**
+ * Class Filesystem
+ * @package think
+ * @mixin Driver
+ * @mixin Local
+ */
+class Filesystem extends Manager
+{
+    protected $namespace = '\\think\\filesystem\\driver\\';
+
+    /**
+     * @param null|string $name
+     * @return Driver
+     */
+    public function disk(string $name = null): Driver
+    {
+        return $this->driver($name);
+    }
+
+    protected function resolveType(string $name)
+    {
+        return $this->getDiskConfig($name, 'type', 'local');
+    }
+
+    protected function resolveConfig(string $name)
+    {
+        return $this->getDiskConfig($name);
+    }
+
+    /**
+     * 获取缓存配置
+     * @access public
+     * @param null|string $name    名称
+     * @param mixed       $default 默认值
+     * @return mixed
+     */
+    public function getConfig(string $name = null, $default = null)
+    {
+        if (!is_null($name)) {
+            return $this->app->config->get('filesystem.' . $name, $default);
+        }
+
+        return $this->app->config->get('filesystem');
+    }
+
+    /**
+     * 获取磁盘配置
+     * @param string $disk
+     * @param null   $name
+     * @param null   $default
+     * @return array
+     */
+    public function getDiskConfig($disk, $name = null, $default = null)
+    {
+        if ($config = $this->getConfig("disks.{$disk}")) {
+            return Arr::get($config, $name, $default);
+        }
+
+        throw new InvalidArgumentException("Disk [$disk] not found.");
+    }
+
+    /**
+     * 默认驱动
+     * @return string|null
+     */
+    public function getDefaultDriver()
+    {
+        return $this->getConfig('default');
+    }
+}
diff --git a/vendor/topthink/think-filesystem/src/facade/Filesystem.php b/vendor/topthink/think-filesystem/src/facade/Filesystem.php
new file mode 100644
index 000000000..0e32c2c2a
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/facade/Filesystem.php
@@ -0,0 +1,33 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\facade;
+
+use think\Facade;
+use think\filesystem\Driver;
+
+/**
+ * Class Filesystem
+ * @package think\facade
+ * @mixin \think\Filesystem
+ * @method static Driver disk(string $name = null) , null|string
+ * @method static mixed getConfig(null|string $name = null, mixed $default = null) 获取缓存配置
+ * @method static array getDiskConfig(string $disk, null $name = null, null $default = null) 获取磁盘配置
+ * @method static string|null getDefaultDriver() 默认驱动
+ */
+class Filesystem extends Facade
+{
+    protected static function getFacadeClass()
+    {
+        return \think\Filesystem::class;
+    }
+}
diff --git a/vendor/topthink/think-filesystem/src/filesystem/Driver.php b/vendor/topthink/think-filesystem/src/filesystem/Driver.php
new file mode 100644
index 000000000..e80414150
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/filesystem/Driver.php
@@ -0,0 +1,130 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\filesystem;
+
+use League\Flysystem\Filesystem;
+use League\Flysystem\FilesystemAdapter;
+use League\Flysystem\UnableToSetVisibility;
+use League\Flysystem\UnableToWriteFile;
+use RuntimeException;
+use think\Cache;
+use think\File;
+
+/**
+ * Class Driver
+ * @package think\filesystem
+ * @mixin Filesystem
+ */
+abstract class Driver
+{
+
+    /** @var Cache */
+    protected $cache;
+
+    /** @var Filesystem */
+    protected $filesystem;
+
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $config = [];
+
+    public function __construct(Cache $cache, array $config)
+    {
+        $this->cache  = $cache;
+        $this->config = array_merge($this->config, $config);
+
+        $adapter          = $this->createAdapter();
+        $this->filesystem = $this->createFilesystem($adapter);
+    }
+
+    abstract protected function createAdapter(): FilesystemAdapter;
+
+    protected function createFilesystem(FilesystemAdapter $adapter): Filesystem
+    {
+        $config = array_intersect_key($this->config, array_flip(['visibility', 'disable_asserts', 'url']));
+
+        return new Filesystem($adapter, $config);
+    }
+
+    /**
+     * 获取文件完整路径
+     * @param string $path
+     * @return string
+     */
+    public function path(string $path): string
+    {
+        return $path;
+    }
+
+    protected function concatPathToUrl($url, $path)
+    {
+        return rtrim($url, '/') . '/' . ltrim($path, '/');
+    }
+
+    public function url(string $path): string
+    {
+        throw new RuntimeException('This driver does not support retrieving URLs.');
+    }
+
+    /**
+     * 保存文件
+     * @param string $path 路径
+     * @param File $file 文件
+     * @param null|string|\Closure $rule 文件名规则
+     * @param array $options 参数
+     * @return bool|string
+     */
+    public function putFile(string $path, File $file, $rule = null, array $options = [])
+    {
+        return $this->putFileAs($path, $file, $file->hashName($rule), $options);
+    }
+
+    /**
+     * 指定文件名保存文件
+     * @param string $path 路径
+     * @param File $file 文件
+     * @param string $name 文件名
+     * @param array $options 参数
+     * @return bool|string
+     */
+    public function putFileAs(string $path, File $file, string $name, array $options = [])
+    {
+        $stream = fopen($file->getRealPath(), 'r');
+        $path   = trim($path . '/' . $name, '/');
+
+        $result = $this->put($path, $stream, $options);
+
+        if (is_resource($stream)) {
+            fclose($stream);
+        }
+
+        return $result ? $path : false;
+    }
+
+    protected function put(string $path, $contents, array $options = [])
+    {
+        try {
+            $this->writeStream($path, $contents, $options);
+        } catch (UnableToWriteFile|UnableToSetVisibility $e) {
+            return false;
+        }
+        return true;
+    }
+
+    public function __call($method, $parameters)
+    {
+        return $this->filesystem->$method(...$parameters);
+    }
+}
diff --git a/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php
new file mode 100644
index 000000000..3b1b64d8c
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php
@@ -0,0 +1,98 @@
+<?php
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: yunwuxin <448901948@qq.com>
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\filesystem\driver;
+
+use League\Flysystem\FilesystemAdapter;
+use League\Flysystem\Local\LocalFilesystemAdapter;
+use League\Flysystem\PathNormalizer;
+use League\Flysystem\PathPrefixer;
+use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
+use League\Flysystem\Visibility;
+use League\Flysystem\WhitespacePathNormalizer;
+use think\filesystem\Driver;
+
+class Local extends Driver
+{
+    /**
+     * 配置参数
+     * @var array
+     */
+    protected $config = [
+        'root' => '',
+    ];
+
+    /**
+     * @var PathPrefixer
+     */
+    protected $prefixer;
+
+    /**
+     * @var PathNormalizer
+     */
+    protected $normalizer;
+
+    protected function createAdapter(): FilesystemAdapter
+    {
+        $visibility = PortableVisibilityConverter::fromArray(
+            $this->config['permissions'] ?? [],
+            $this->config['visibility'] ?? Visibility::PRIVATE
+        );
+
+        $links = ($this->config['links'] ?? null) === 'skip'
+            ? LocalFilesystemAdapter::SKIP_LINKS
+            : LocalFilesystemAdapter::DISALLOW_LINKS;
+
+        return new LocalFilesystemAdapter(
+            $this->config['root'],
+            $visibility,
+            $this->config['lock'] ?? LOCK_EX,
+            $links
+        );
+    }
+
+    protected function prefixer()
+    {
+        if (!$this->prefixer) {
+            $this->prefixer = new PathPrefixer($this->config['root'], DIRECTORY_SEPARATOR);
+        }
+        return $this->prefixer;
+    }
+
+    protected function normalizer()
+    {
+        if (!$this->normalizer) {
+            $this->normalizer = new WhitespacePathNormalizer();
+        }
+        return $this->normalizer;
+    }
+
+    /**
+     * 获取文件访问地址
+     * @param string $path 文件路径
+     * @return string
+     */
+    public function url(string $path): string
+    {
+        $path = $this->normalizer()->normalizePath($path);
+
+        if (isset($this->config['url'])) {
+            return $this->concatPathToUrl($this->config['url'], $path);
+        }
+        return parent::url($path);
+    }
+
+    public function path(string $path): string
+    {
+        return $this->prefixer()->prefixPath($path);
+    }
+}
diff --git a/vendor/topthink/think-filesystem/tests/FilesystemTest.php b/vendor/topthink/think-filesystem/tests/FilesystemTest.php
new file mode 100644
index 000000000..cc9d94e09
--- /dev/null
+++ b/vendor/topthink/think-filesystem/tests/FilesystemTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace think\tests;
+
+use Mockery as m;
+use Mockery\MockInterface;
+use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamDirectory;
+use PHPUnit\Framework\TestCase;
+use think\App;
+use think\Config;
+use think\Container;
+use think\Filesystem;
+use think\filesystem\driver\Local;
+
+class FilesystemTest extends TestCase
+{
+    /** @var App|MockInterface */
+    protected $app;
+
+    /** @var Filesystem */
+    protected $filesystem;
+
+    /** @var Config|MockInterface */
+    protected $config;
+
+    /** @var vfsStreamDirectory */
+    protected $root;
+
+    protected function setUp(): void
+    {
+        $this->app = m::mock(App::class)->makePartial();
+        Container::setInstance($this->app);
+        $this->app->shouldReceive('make')->with(App::class)->andReturn($this->app);
+        $this->config = m::mock(Config::class);
+        $this->config->shouldReceive('get')->with('filesystem.default', null)->andReturn('local');
+        $this->app->shouldReceive('get')->with('config')->andReturn($this->config);
+        $this->filesystem = new Filesystem($this->app);
+
+        $this->root = vfsStream::setup('rootDir');
+    }
+
+    protected function tearDown(): void
+    {
+        m::close();
+    }
+
+    public function testDisk()
+    {
+        $this->config->shouldReceive('get')->with('filesystem.disks.local', null)->andReturn([
+            'type' => 'local',
+            'root' => $this->root->url(),
+        ]);
+
+        $this->config->shouldReceive('get')->with('filesystem.disks.foo', null)->andReturn([
+            'type' => 'local',
+            'root' => $this->root->url(),
+        ]);
+
+        $this->assertInstanceOf(Local::class, $this->filesystem->disk());
+
+        $this->assertInstanceOf(Local::class, $this->filesystem->disk('foo'));
+    }
+
+}
+
diff --git a/vendor/topthink/think-filesystem/tests/bootstrap.php b/vendor/topthink/think-filesystem/tests/bootstrap.php
new file mode 100644
index 000000000..a4abe2daf
--- /dev/null
+++ b/vendor/topthink/think-filesystem/tests/bootstrap.php
@@ -0,0 +1,2 @@
+<?php
+