初始化-安装依赖

This commit is contained in:
2026-03-03 10:06:12 +08:00
parent 3f349a35a4
commit ec8cac4221
187 changed files with 26292 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
<?php
namespace plugin\saiadmin\service\storage;
use plugin\saiadmin\app\logic\system\SystemConfigLogic;
use plugin\saiadmin\app\model\system\SystemAttachment;
use plugin\saiadmin\exception\ApiException;
use plugin\saiadmin\utils\Arr;
/**
* 切片上传服务
*/
class ChunkUploadService
{
/**
* 基础配置
*/
protected $config;
protected $path;
protected $folder = "chunk";
/**
* 初始化切片上传服务
*/
public function __construct($folder = "chunk")
{
$logic = new SystemConfigLogic();
$this->folder = $folder;
$this->config = $logic->getGroup('upload_config');
$this->path = $this->checkPath();
}
/**
* 检查并创建上传路径
* @return string
*/
public function checkPath(): string
{
$root = Arr::getConfigValue($this->config, 'local_root');
$path = base_path() . DIRECTORY_SEPARATOR . $root . $this->folder . DIRECTORY_SEPARATOR;
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
return $path;
}
/**
* 检查切片文件上传状态
* @param $data
* @return array
*/
public function checkChunk($data): array
{
$allow_file = Arr::getConfigValue($this->config, 'upload_allow_file');
if (!in_array($data['ext'], explode(',', $allow_file))) {
throw new ApiException('不支持该格式的文件上传');
}
// 检查已经上传的分片文件
for ($i = 0; $i < $data['total']; ++$i) {
$chunkFile = $this->path . "{$data['hash']}_{$data['total']}_{$i}.chunk";
if (!file_exists($chunkFile)) {
if ($i == 0) {
return $this->uploadChunk($data);
} else {
return ['chunk' => $i, 'status' => 'resume'];
}
}
}
// 分片文件已经全部上传
return ['chunk' => $i, 'status' => 'success'];
}
/**
* 上传切片
* @param $data
* @return array
*/
public function uploadChunk($data): array
{
$allow_file = Arr::getConfigValue($this->config, 'upload_allow_file');
if (!in_array($data['ext'], explode(',', $allow_file))) {
throw new ApiException('不支持该格式的文件上传');
}
$request = request();
if (!$request) {
throw new ApiException('切片上传服务必须在 HTTP 请求环境下调用');
}
$uploadFile = current($request->file());
$chunkName = $this->path . "{$data['hash']}_{$data['total']}_{$data['index']}.chunk";
$uploadFile->move($chunkName);
if (($data['index'] + 1) == $data['total']) {
return $this->mergeChunk($data);
}
return ['chunk' => $data['index'], 'status' => 'success'];
}
/**
* 合并切片文件
* @param $data
* @return array
*/
public function mergeChunk($data): array
{
$filePath = $this->path . $data['hash'] . '.' . $data['ext'];
$fileHandle = fopen($filePath, 'w');
for ($i = 0; $i < $data['total']; ++$i) {
$chunkFile = $this->path . "{$data['hash']}_{$data['total']}_{$i}.chunk";
if (!file_exists($chunkFile)) {
throw new ApiException('切片文件查找失败,请重新上传');
}
fwrite($fileHandle, file_get_contents($chunkFile));
unlink($chunkFile);
}
$domain = Arr::getConfigValue($this->config, 'local_domain');
$uri = Arr::getConfigValue($this->config, 'local_uri');
$baseUrl = $domain . $uri . $this->folder . '/';
$save_path = Arr::getConfigValue($this->config, 'local_root') . $this->folder . '/';
$object_name = $data['hash'] . '.' . $data['ext'];
$info['storage_mode'] = 1;
$info['category_id'] = 1;
$info['origin_name'] = $data['name'];
$info['object_name'] = $object_name;
$info['hash'] = $data['hash'];
$info['mime_type'] = $data['type'];
$info['storage_path'] = $save_path . $object_name;
$info['suffix'] = $data['ext'];
$info['size_byte'] = $data['size'];
$info['size_info'] = formatBytes($data['size']);
$info['url'] = $baseUrl . $object_name;
SystemAttachment::create($info);
return $info;
}
}

View File

@@ -0,0 +1,136 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\service\storage;
use plugin\saiadmin\app\logic\system\SystemConfigLogic;
use plugin\saiadmin\exception\ApiException;
use plugin\saiadmin\utils\Arr;
/**
* 文件上传服务
* @method static array uploadFile(array $config = []) 上传文件
* @method static array uploadBase64(string $base64, string $extension = 'png') 上传Base64文件
* @method static array uploadServerFile(string $file_path) 上传服务端文件
*/
class UploadService
{
/**
* @desc 存储磁盘
* @param int $type
* @param string $upload
* @param bool $_is_file_upload
* @return mixed
*/
public static function disk(int $type = 1, string $upload = 'image', bool $_is_file_upload = true)
{
$logic = new SystemConfigLogic();
$uploadConfig = $logic->getGroup('upload_config');
$file = current(request()->file());
$ext = $file->getUploadExtension() ?: null;
$file_size = $file->getSize();
if ($file_size > Arr::getConfigValue($uploadConfig, 'upload_size')) {
throw new ApiException('文件大小超过限制');
}
$allow_file = Arr::getConfigValue($uploadConfig, 'upload_allow_file');
$allow_image = Arr::getConfigValue($uploadConfig, 'upload_allow_image');
if ($upload == 'image') {
if (!in_array($ext, explode(',', $allow_image))) {
throw new ApiException('不支持该格式的文件上传');
}
} else {
if (!in_array($ext, explode(',', $allow_file))) {
throw new ApiException('不支持该格式的文件上传');
}
}
switch ($type) {
case 1:
// 本地
$config = [
'adapter' => \Tinywan\Storage\Adapter\LocalAdapter::class,
'root' => Arr::getConfigValue($uploadConfig, 'local_root'),
'dirname' => function () {
return date('Ymd');
},
'domain' => Arr::getConfigValue($uploadConfig, 'local_domain'),
'uri' => Arr::getConfigValue($uploadConfig, 'local_uri'),
'algo' => 'sha1',
];
break;
case 2:
// 阿里云
$config = [
'adapter' => \Tinywan\Storage\Adapter\OssAdapter::class,
'accessKeyId' => Arr::getConfigValue($uploadConfig, 'oss_accessKeyId'),
'accessKeySecret' => Arr::getConfigValue($uploadConfig, 'oss_accessKeySecret'),
'bucket' => Arr::getConfigValue($uploadConfig, 'oss_bucket'),
'dirname' => Arr::getConfigValue($uploadConfig, 'oss_dirname'),
'domain' => Arr::getConfigValue($uploadConfig, 'oss_domain'),
'endpoint' => Arr::getConfigValue($uploadConfig, 'oss_endpoint'),
'algo' => 'sha1',
];
break;
case 3:
// 七牛
$config = [
'adapter' => \Tinywan\Storage\Adapter\QiniuAdapter::class,
'accessKey' => Arr::getConfigValue($uploadConfig, 'qiniu_accessKey'),
'secretKey' => Arr::getConfigValue($uploadConfig, 'qiniu_secretKey'),
'bucket' => Arr::getConfigValue($uploadConfig, 'qiniu_bucket'),
'dirname' => Arr::getConfigValue($uploadConfig, 'qiniu_dirname'),
'domain' => Arr::getConfigValue($uploadConfig, 'qiniu_domain'),
];
break;
case 4:
// 腾讯云
$config = [
'adapter' => \Tinywan\Storage\Adapter\CosAdapter::class,
'secretId' => Arr::getConfigValue($uploadConfig, 'cos_secretId'),
'secretKey' => Arr::getConfigValue($uploadConfig, 'cos_secretKey'),
'bucket' => Arr::getConfigValue($uploadConfig, 'cos_bucket'),
'dirname' => Arr::getConfigValue($uploadConfig, 'cos_dirname'),
'domain' => Arr::getConfigValue($uploadConfig, 'cos_domain'),
'region' => Arr::getConfigValue($uploadConfig, 'cos_region'),
];
break;
case 5:
// s3 亚马逊
$config = [
'adapter' => \Tinywan\Storage\Adapter\S3Adapter::class,
'key' => Arr::getConfigValue($uploadConfig, 's3_key'),
'secret' => Arr::getConfigValue($uploadConfig, 's3_secret'),
'bucket' => Arr::getConfigValue($uploadConfig, 's3_bucket'),
'dirname' => Arr::getConfigValue($uploadConfig, 's3_dirname'),
'domain' => Arr::getConfigValue($uploadConfig, 's3_domain'),
'region' => Arr::getConfigValue($uploadConfig, 's3_region'),
'version' => Arr::getConfigValue($uploadConfig, 's3_version'),
// 'use_path_style_endpoint' => Arr::getConfigValue($uploadConfig,'s3_use_path_style_endpoint'),
'use_path_style_endpoint' => filter_var(Arr::getConfigValue($uploadConfig, 's3_use_path_style_endpoint'), FILTER_VALIDATE_BOOLEAN),
'endpoint' => Arr::getConfigValue($uploadConfig, 's3_endpoint'),
'acl' => Arr::getConfigValue($uploadConfig, 's3_acl'),
];
break;
default:
throw new ApiException('该上传模式不存在');
}
return new $config['adapter'](array_merge(
$config,
['_is_file_upload' => $_is_file_upload]
));
}
/**
* @param $name
* @param $arguments
* @return mixed
* @author Tinywan(ShaoBo Wan)
*/
public static function __callStatic($name, $arguments)
{
return static::disk()->{$name}(...$arguments);
}
}