[ 'storage_type' => '文件存储类型', ], 'local' => [ 'storage_local_exts' => '文件上传允许类型后缀', ], 'oss' => [ 'storage_oss_domain' => '文件访问域名', 'storage_oss_keyid' => '接口授权AppId', 'storage_oss_secret' => '接口授权AppSecret', 'storage_oss_bucket' => '文件存储空间名称', 'storage_oss_is_https' => '文件HTTP访问协议', 'storage_oss_endpoint' => '文件存储节点域名', ], 'qiniu' => [ 'storage_qiniu_region' => '文件存储节点', 'storage_qiniu_domain' => '文件访问域名', 'storage_qiniu_bucket' => '文件存储空间名称', 'storage_qiniu_is_https' => '文件HTTP访问协议', 'storage_qiniu_access_key' => '接口授权AccessKey', 'storage_qiniu_secret_key' => '接口授权SecretKey', ], ]; /** * 静态魔术方法 * @param string $name * @param array $arguments * @return mixed * @throws Exception */ public static function __callStatic($name, $arguments) { if (method_exists($class = self::instance(self::$config->get('storage_type')), $name)) { return call_user_func_array([$class, $name], $arguments); } throw new Exception("File driver method not exists: " . get_class($class) . "->{$name}"); } /** * 设置文件驱动名称 * @param string $name * @return \library\driver\Local * @throws Exception */ public static function instance($name) { if (isset(self::$object[$class = ucfirst(strtolower($name))])) { return self::$object[$class]; } if (class_exists($object = __NAMESPACE__ . "\\driver\\{$class}")) { return self::$object[$class] = new $object; } throw new Exception("File driver [{$class}] does not exist."); } /** * 根据文件后缀获取文件MINE * @param array $ext 文件后缀 * @param array $mine 文件后缀MINE信息 * @return string */ public static function mine($ext, $mine = []) { $mines = self::mines(); foreach (is_string($ext) ? explode(',', $ext) : $ext as $e) { $mine[] = isset($mines[strtolower($e)]) ? $mines[strtolower($e)] : 'application/octet-stream'; } return join(',', array_unique($mine)); } /** * 获取所有文件扩展的mine * @return mixed */ public static function mines() { $mines = cache('all_ext_mine'); if (empty($mines)) { $content = file_get_contents('http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); preg_match_all('#^([^\s]{2,}?)\s+(.+?)$#ism', $content, $matches, PREG_SET_ORDER); foreach ($matches as $match) foreach (explode(" ", $match[2]) as $ext) $mines[$ext] = $match[1]; cache('all_ext_mine', $mines); } return $mines; } /** * 获取文件相对名称 * @param string $url 文件链接 * @param string $ext 文件后缀 * @param string $pre 文件前缀(若有值需要以/结尾) * @param string $fun 文件名生成方法 * @return string */ public static function name($url, $ext = '', $pre = '', $fun = 'md5') { empty($ext) && $ext = pathinfo($url, 4); empty($ext) || $ext = trim($ext, '.\\/'); empty($pre) || $pre = trim($pre, '.\\/'); $splits = array_merge([$pre], str_split($fun($url), 16)); return trim(join('/', $splits), '/') . '.' . strtolower($ext ? $ext : 'tmp'); } /** * 下载文件到本地 * @param string $url 文件URL地址 * @param boolean $force 是否强制重新下载文件 * @return array */ public static function down($url, $force = false) { try { $file = self::instance('local'); $name = self::name($url, '', 'down/'); if (empty($force) && $file->has($name)) return $file->info($name); return $file->save($name, file_get_contents($url)); } catch (\Exception $e) { Log::error(__METHOD__ . " File download failed [ {$url} ] {$e->getMessage()}"); return ['url' => $url, 'hash' => md5($url), 'key' => $url, 'file' => $url]; } } /** * 文件储存初始化 * @param array $data * @throws Exception * @throws \think\exception\PDOException */ public static function init($data = []) { if (empty(self::$config) && function_exists('sysconf')) { foreach (self::$params as $arr) { foreach (array_keys($arr) as $key) { $data[$key] = sysconf($key); } } } self::$config = new Options($data); } } try { // 初始化存储 File::init(); // \think\facade\Log::info(__METHOD__ . ' File storage initialization success'); } catch (\Exception $e) { Log::error(__METHOD__ . " File storage initialization exception. [{$e->getMessage()}]"); }