| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- <?php
- /**
- * 重庆赤晓店信息科技有限公司
- * https://www.chixiaodian.com
- * Copyright (c) 2023 赤店商城 All rights reserved.
- */
- namespace app\models\common;
- use app\librarys\storage\components\StorageComponent;
- use app\librarys\storage\drivers\Aliyun;
- use app\librarys\storage\drivers\Local;
- use app\librarys\storage\drivers\Qcloud;
- use app\librarys\storage\drivers\Qiniu;
- use app\librarys\storage\helpers\UrlConverter;
- use app\librarys\storage\UploadFile;
- use app\models\Option;
- use app\models\Storage;
- use app\models\UploadConfig;
- use yii\base\Model;
- use yii\helpers\Json;
- use app\constants\OptionSetting;
- /**
- * 上传工具类
- * Class Upload
- * @package app\models\common
- * @property UploadConfig $upload_config
- */
- class Upload extends Model
- {
- public $upload_config;
- public $store_id = 1;
- public $mch_id = 0;
- public $supplier_id = 0;
- public $bd_id = 0;
- public $parent_id = 0;
- // 获取图片样式
- public static function getImgStyle($imgUrl, $store_id = 0)
- {
- if (empty($imgUrl)) {
- return $imgUrl;
- }
- if (!$store_id) {
- $store_id = \get_store_id();
- }
- $config = null;
- if (\Yii::$app->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
- ];
- }
- }
|