isSaas()) { $is_use_platform = (bool)Option::get(OptionSetting::MCH_HIDE_OSS, 0, 'saas', '0')['value']; if ($is_use_platform) { $config = UploadConfig::findOne(['store_id' => 0, 'is_delete' => 0]); if (!$config) { return $imgUrl; } } } if (!$config) { $config = UploadConfig::findOne(['store_id' => $store_id, 'is_delete' => 0]); if (!$config) { return $imgUrl; } } if ($config->storage_type == 'local') { return $imgUrl; } $params = Json::decode($config->{$config->storage_type}); if ($params && isset($params['style']) && !empty($params['style'])) { $style = $params['style']; // Todo 还有很多细节需要处理 if ($config->storage_type == 'aliyun') { return $imgUrl . '?x-oss-process=style/' . $style; } if ($config->storage_type == 'qcloud') { $find = $params['bucket']; if (\strpos($imgUrl, $find) !== false) { return $imgUrl . '/' . $style; } if (isset($params['domain']) && !empty($params['domain'])) { $find = $params['domain']; if (\strpos($imgUrl, $find) !== false) { return $imgUrl . '/' . $style; } } } if ($config->storage_type == 'qiniu') { if (isset($params['domain']) && !empty($params['domain'])) { $find = $params['domain']; if (\strpos($imgUrl, $find) !== false) { return $imgUrl . '-' . $style; } } } } return $imgUrl; } /** * 获取文件最大上传大小 * @return mixed */ public static function getMaxUploadSize($type = Storage::TYPE_IMAGE, $supplier_id = 0) { $upload_max_size = self::getMaxFileSizeByte('upload_max_filesize'); $upload_max_size = intval($upload_max_size / (1024 * 1024)); $post_max_size = self::getMaxFileSizeByte('post_max_size'); $post_max_size = intval($post_max_size / (1024 * 1024)); // 商户是否使用平台配置 if (\Yii::$app->isSaas()) { $is_use_platform = (bool)Option::get(OptionSetting::MCH_HIDE_OSS, 0, 'saas', '0')['value']; if ($supplier_id) { $is_use_platform = 1; } $upload_limit = Option::get(OptionSetting::PLATFORM_UPLOAD_LIMIT, 0, 'saas', json_encode([ 'max_picture' => 10, 'over_picture' => 0, 'max_file' => 10, 'over_file' => 0 ]))['value']; if ($is_use_platform) { $upload_limit = Json::decode($upload_limit); if (!isset($upload_limit['over_file'])) { $upload_limit['over_file'] = $upload_limit['over_picture']; } if (!isset($upload_limit['max_file'])) { $upload_limit['max_file'] = $upload_limit['max_picture']; } if ($type != Storage::TYPE_IMAGE) { if ($upload_limit['over_file'] > 0) { return min($upload_max_size, $post_max_size); } else { return min($upload_max_size, $upload_limit['max_file'], $post_max_size); } } else { if ($upload_limit['over_picture'] > 0) { return min($upload_max_size, $post_max_size); } else { return min($upload_max_size, $upload_limit['max_picture'], $post_max_size); } } } } // 获取后台越限配置 $options = Option::get('overrun', get_store_id(), 'store'); if (!$options['value']) { return min($upload_max_size, $post_max_size); } else { $options = Json::decode($options['value']); if ($type != Storage::TYPE_IMAGE) { if ($options['over_file'] > 0) { return min($upload_max_size, $post_max_size); } else { return min($upload_max_size, $options['max_file'], $post_max_size); } } else { if ($options['over_picture'] > 0) { return min($upload_max_size, $post_max_size); } else { return min($upload_max_size, $options['max_picture'], $post_max_size); } } } } /** * @param $type * @param int $dec * @return float */ private static function getMaxFileSizeByte($type, $dec = 2) { $max_size = ini_get($type); preg_match('/(^[0-9\.]+)(\w+)/', $max_size, $info); $size = $info[1]; $suffix = strtoupper($info[2]); $a = array_flip(array("B", "KB", "MB", "GB", "TB", "PB")); $b = array_flip(array("B", "K", "M", "G", "T", "P")); $pos = isset($a[$suffix]) && $a[$suffix] !== 0 ? $a[$suffix] : $b[$suffix]; return round($size * pow(1024, $pos), $dec); } private function getFileType($extension) { $type_list = [ 'image' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp',], 'video' => ['mp4', 'flv', 'ogg', 'mov',], ]; foreach ($type_list as $type => $exs) { if (in_array($extension, $exs)) { return $type . "/" . $extension; } } return ''; } private function mkdir($dir) { if (!is_dir($dir)) { if (!$this->mkdir(dirname($dir))) { return false; } if (!mkdir($dir)) { return false; } } return true; } /** * @param null $name * @return array */ public function setDriver($name = null) { /** * @var StorageComponent $storage */ $storage = \Yii::$app->storage; $driver = $this->getDriverConf(); $storage->setDriver($driver); return $storage->getUploadedFile($name); } public function getDriverConf() { switch ($this->upload_config->storage_type) { case Storage::PLATFORM_ALIYUN: $config = Json::decode($this->upload_config->aliyun); $driver = [ 'class' => Aliyun::class, 'accessKey' => $config['access_key'], 'secretKey' => $config['secret_key'], 'bucket' => $config['bucket'], 'isCName' => $config['CNAME'], 'endPoint' => $config['domain'], ]; $driver['urlCallback'] = function ($objectUrl, $saveTo) use ($config) { $url = $objectUrl; if ($config['style_api']) { $url = $url . '?' . $config['style_api']; } return $url; }; break; case Storage::PLATFORM_QINIU: $config = Json::decode($this->upload_config->qiniu); if(!$config['domain']){ $configq = Json::decode($this->upload_config->qcloud); $config['domain'] = $configq['region']; } $driver = [ 'class' => Qiniu::class, //saas后台配置参数名是secret_ke,独立商城参数名是access_key 'accessKey' => isset($config['secret_ke']) ? $config['secret_ke'] : $config['access_key'], 'secretKey' => $config['secret_key'], 'region' => $config['domain'], 'bucket' => $config['bucket'], 'zone' => $config['zone'], ]; $driver['urlCallback'] = function ($objectUrl, $saveTo) use ($config) { $url = $config['domain'] . '/' . $saveTo; if ($config['style_api']) { $url = $url . '?' . $config['style_api']; } return $url; }; break; case Storage::PLATFORM_QCLOUD: $config = Json::decode($this->upload_config->qcloud); preg_match('/(.*?)-(\d+)\.cos\.?(.*?)\.myqcloud\.com/', $config['region'], $region); if (!$region || $region == 0) { return [ 'code' => 1, 'msg' => '默认域名不正确' ]; } $driver = [ 'class' => Qcloud::class, 'accessKey' => $config['secret_id'], 'secretKey' => $config['secret_key'], 'bucket' => $config['bucket'], 'region' => $region[3], 'appId' => $region[2], 'urlCallBack' => function ($objectUrl, $saveTo) use ($config) { $url = ($config['domain'] ? $config['domain'] : $config['region']) . '/' . $saveTo; if ($config['style']) { $url = $url . '?' . $config['style']; } return $url; } ]; break; default: $driver = [ 'class' => Local::class ]; break; } return $driver; } /** * 临时文件存储 * @param integer $type * @return array */ public function saveFileTemp($type = Storage::TYPE_IMAGE) { $name = $type === Storage::TYPE_IMAGE ? 'image' : 'video'; /** * @var StorageComponent $storageTemp */ $storageTemp = \Yii::$app->storageTemp; $storageTemp->setDriver([ 'class' => Local::class ]); $file = $storageTemp->getUploadedFile($name); $checkRes = $this->checkSize($file, $type); if ($checkRes['code'] == 1) { return [ 'code' => 1, 'msg' => $checkRes['msg'] ]; } try { $url = $file->saveAsUniqueHash(); if (!$url) { return [ 'code' => 1, 'msg' => '文件创建失败' ]; } $res = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'url' => $url, 'extension' => $file->extension, 'size' => $file->size, 'type' => $this->getFileType($file->extension) ] ]; return $res; } catch (\Exception $e) { return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } /** * 获取文件保存目录 * @param $name * @param integer $type * @return string */ public function getUploadDir($name, $type = Storage::TYPE_IMAGE) { $timeDir = date('Y-m-d'); $typeDir = $type === Storage::TYPE_IMAGE ? 'images' : 'videos'; $dir = sprintf('%s/store_%d/%s/%s', $typeDir, $this->store_id, $timeDir, $name); if ($this->mch_id > 0) { $dir = sprintf('%s/store_%d/mch_%d/%s/%s', $typeDir, $this->store_id, $this->mch_id, $timeDir, $name); } if ($this->supplier_id > 0) { $dir = sprintf('%s/supplier_%d/%s/%s', $typeDir, $this->supplier_id, $timeDir, $name); } if ($this->bd_id > 0) { $dir = sprintf('%s/bd_%d/%s/%s', $typeDir, $this->bd_id, $timeDir, $name); } return $dir; } /** * 检查文件mime和扩展名 * @param $ext * @param $mime * @param int $type * @return bool */ public function checkMime($ext, $mime, $type = Storage::TYPE_IMAGE) { $extType = Storage::IMAGE_TYPE; $mimeType = Storage::IMAGE_MIME; if ($type == Storage::TYPE_VIDEO) { $extType = Storage::VIDEO_TYPE; $mimeType = Storage::VIDEO_MIME; } if ($type == Storage::TYPE_AUDIO) { $extType = Storage::AUDIO_TYPE; $mimeType = Storage::AUDIO_MIME; } if ($type == Storage::TYPE_XlSX) { $extType = Storage::XlSX_TYPE; $mimeType = Storage::XlSX_MIME; } if ($type == Storage::TYPE_CRT || $type == Storage::TYPE_CER) { $extType = Storage::CRT_TYPE; $mimeType = Storage::CRT_MIME; } if ($type == Storage::TYPE_APK) { $extType = Storage::APK_TYPE; $mimeType = Storage::APK_MIME; } if ($type == Storage::TYPE_PFX) { $extType = Storage::PFX_TYPE; $mimeType = Storage::PFX_MIME; } if ($type == Storage::TYPE_PEM) { $extType = Storage::PEM_TYPE; $mimeType = Storage::PEM_MIME; } if (in_array($ext, $extType) && in_array($mime, $mimeType)) { return true; } return false; } //获取网络图片到临时目录 public function saveTempImage($url) { if (strpos($url, 'http') === false) { $url = 'http:' . trim($url); } if (!is_dir(\Yii::$app->runtimePath . '/image')) { mkdir(\Yii::$app->runtimePath . '/image'); } $save_path = \Yii::$app->runtimePath . '/image/' . md5($url) . '.jpg'; \app\utils\CurlHelper::download($url, $save_path); return $save_path; } //下载保存图片 public function downloadImg($url = '') { $type = Storage::TYPE_IMAGE; try { $tmpfile = $this->saveTempImage($url); $uniqueName = md5($url . md5(microtime(true))); $saveDir = $this->getUploadDir($uniqueName, $type); $this->setDriver('images'); $path = \Yii::$app->storage->getBasePath() . '/' . $saveDir . '.jpg'; $saveFile = \Yii::$app->storage->driver->saveFile($tmpfile, $path); @unlink($tmpfile); if ($saveFile) { return [ 'code' => 0, 'msg' => 'ok', 'url' => $saveFile, ]; } return [ 'code' => 1, 'msg' => '图片保存错误', ]; } catch (\Throwable $throwable) { \Yii::error([__METHOD__, '$throwable', $throwable]); return [ 'code' => 1, 'msg' => $throwable->getMessage(), ]; } } /** * 上传文件 * @param int $type * @return array */ public function uploadFile($type = Storage::TYPE_IMAGE) { $name = 'images'; if ($type === Storage::TYPE_VIDEO) { $name = 'videos'; } elseif ($type === Storage::TYPE_AUDIO) { $name = 'audios'; } elseif ($type === Storage::TYPE_XlSX) { $name = 'xlsx'; } elseif ($type === Storage::TYPE_CRT) { $name = 'crt'; } elseif ($type === Storage::TYPE_APK) { $name = 'apk'; } elseif ($type === Storage::TYPE_PFX) { $name = 'pfx'; } elseif ($type === Storage::TYPE_CER) { $name = 'cer'; } elseif ($type === Storage::TYPE_PEM) { $name = 'pem'; } // $name = $type === Storage::TYPE_IMAGE ? 'images' : 'videos'; $files = $this->setDriver($name); $results = []; foreach ($files as $file) { /** * @var UploadFile $file */ $result = [ 'status' => true, ]; try { $checkRes = $this->checkSize($file, $type); if ($checkRes['code'] == 1) { throw new \Exception($checkRes['msg']); } $uniqueName = sha1_file($file->tempName); $saveDir = $this->getUploadDir($uniqueName, $type); $url = $file->saveWithOriginalExtension($saveDir); $result['url'] = $url; if (strpos($url, 'http') === false) { $result['url'] = 'https://' . $url; } $this->saveStorage($file, $saveDir, $result['url'], $type); } catch (\Throwable $throwable) { $result = [ 'status' => false, 'error' => $throwable->getMessage(), ]; } $results[] = $result; } return $results; } /** * 客户端上传文件 * @param int $type * @return array */ public function uploadClientFile($type = Storage::TYPE_IMAGE) { $name = $type === Storage::TYPE_IMAGE ? 'image' : 'video'; /** * @var UploadFile $file */ $file = $this->setDriver($name); try { $result = [ 'code' => 0, 'msg' => 'success', ]; $checkRes = $this->checkSize($file, $type); if ($checkRes['code'] == 1) { throw new \Exception($checkRes['msg']); } $uniqueName = sha1_file($file->tempName); $saveDir = $this->getUploadDir($uniqueName, $type); $url = $file->saveWithOriginalExtension($saveDir); $result['url'] = $url; if (strpos($url, 'http') === false) { $result['url'] = 'https://' . $url; } if ($type === Storage::TYPE_VIDEO) { $result['cover_pic_url'] = ''; if ($this->upload_config->storage_type == Storage::PLATFORM_QINIU) { if (!empty($result['url'])) { $result['cover_pic_url'] = $result['url'] . '?vframe/jpg/offset/1/w/200/h/200'; } } } } catch (\Throwable $throwable) { \Yii::error([__METHOD__, '$throwable', $throwable]); $result = [ 'code' => 1, 'msg' => $throwable->getMessage(), ]; } return $result; } /** * 本地文件上传到云 * @param $file * @return array */ public function local2cloud($file) { $cache = cache(); $k = ['local2cloud', $file]; $v = $cache->get($k); if($v){ return [ 'cache' => true, 'status' => true, 'url' => $v, ]; } $storage = \Yii::$app->storageTemp; $storage->setDriver($this->getDriverConf()); $driver = $storage->getDriver(); if ($driver instanceof Local){ return null; } $result = [ 'status' => true, 'cache' => false, ]; try { $uniqueName = sha1_file($file) . '.' . strtolower(pathinfo($file, PATHINFO_EXTENSION)); $saveDir = $this->getUploadDir($uniqueName, Storage::TYPE_IMAGE); $saveDir = rtrim($storage->basePath, '/') . '/' . ltrim($saveDir, '/'); $url = $driver->saveFile($file, $saveDir); $result['url'] = $url; if (strpos($url, 'http') === false) { $result['url'] = 'https://' . $url; } $cache->set($k, $result['url']); } catch (\Throwable $throwable) { \Yii::error($throwable); $result = [ 'status' => false, 'error' => $throwable->getMessage(), ]; } return $result; } /** * 本地文件上传到云 * @param $file * @return $file */ public function local2cloudLink($file) { $local2cloud = $this->local2cloud($file); if($local2cloud && $local2cloud['status']){ return $local2cloud['url']; } return null; } /** * @param UploadFile $file * @param $saveDir * @param $url * @param $type * @return bool */ public function saveStorage(UploadFile $file, $saveDir, $url, $type) { $form = new Storage(); $form->parent_id = $this->parent_id; $form->name = $file->getBaseName(); $form->mime = $file->type; $form->ext = $file->getExtension(); $form->size = $file->size; $path = \Yii::$app->storage->getBasePath() . '/' . $saveDir . '.' . $file->getExtension(); $form->path = $path; $form->url = $url; $form->platform = isset($this->upload_config->storage_type) ? $this->upload_config->storage_type : Storage::PLATFORM_LOCAL; $form->type = $type; $form->store_id = $this->store_id; $form->mch_id = $this->mch_id; $form->supplier_id = $this->supplier_id; $form->bd_id = $this->bd_id; return $form->save(); } /** * 检查文件大小 * @param UploadFile $file * @param int $type * @return array */ public function checkSize(UploadFile $file, $type = Storage::TYPE_IMAGE) { $maxUploadSize = self::getMaxUploadSize($type, $this->supplier_id); $uploadSize = $maxUploadSize * 1024 * 1024; // 检查mime和扩展名 if (false === $this->checkMime($file->getExtension(), $file->type, $type)) { return [ 'code' => 1, 'msg' => '文件格式不正确' ]; } // 检查文件大小 if ($file->size > $uploadSize) { return [ 'code' => 1, 'msg' => '上传文件超过 ' . ($maxUploadSize ?: 0) . 'M' ]; } return [ 'code' => 0 ]; } }