Files
ntonpower/extend/storage/LocalUploader.php
2026-10-14 14:00:29 +08:00

205 lines
6.3 KiB
PHP

<?php
namespace storage;
use FceskyUpload\contract\FileInfo;
use FceskyUpload\UploadManager;
use FceskyUpload\drivers\LocalDriver;
class LocalUploader
{
private $config = [];
private $domain = "";
private $_error = "";
public function __construct($conf = [])
{
$this->config = [
'disks' => [
'local' => [
'driver' => LocalDriver::class, //上传类
'save_dir' => app()->getRootPath() . 'public/attachment', //上传保存路径
'file_path' => '/attachment', //上传保存路径
'tmp_dir' => root_path('runtime' . DIRECTORY_SEPARATOR . 'uploadtmp'),//临时目录
'slice_first' => 0, //从第几片开始
],
//继续添加其它仓库
],
'default' => [
'disk' => 'local', //默认磁盘
'extensions' => 'jpg,png,mp4', //后缀
'mimeTypes' => 'image/*,video/*', //类型
'middlewares' => [], //中间件数组
'maxSize' => 1 * 1024 * 1024, //单包最大上传大小 2M
]
];
}
/**文件上传
* @param $data
* @param $file
* @return array
*/
public function uploadFile($data, $file)
{
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
exit; // finish preflight CORS requests here
}
try {
//处理部分数据
$data['size'] = $file->getSize();
$data['name'] = $file->getOriginalName();
$data['ext'] = $file->extension();
//检测文件大小
if (!$this->checkSize($data['size'])) {
$this->_error = "超出文件上传大小限制";
return ['code' => -1, 'data' => []];
}
$config = $this->config;
$uploadManager = new UploadManager($config);
$fileInfo = new FileInfo();
$fileInfo->identifier = $data['hash'];
$fileInfo->filename = $data['name'];
$fileInfo->chunkNumber = $data['chunk'] ?? 0;;
$fileInfo->chunkNumber = intval($fileInfo->chunkNumber ?? 0);
//未设置分片数量 则默认总数为1 当前为0
$fileInfo->totalChunks = $data['chunks'] ?? 1;
$fileInfo->totalChunks = intval($fileInfo->totalChunks ?? 1);
$fileInfo->totalChunks = ($fileInfo->totalChunks > 0) ? $fileInfo->totalChunks : 1;
$fileInfo->totalSize = $data['size'];
//获取后缀
$fileInfo->ext = $data['ext'];
if (!$this->checkFileType($fileInfo->ext)) {
$this->_error = "禁止上传的文件类型";
return ['code' => -1, 'data' => []];
}
$upload = $uploadManager->uploadFile($fileInfo);
//如果文件较小 直接上传完成
if (isset($upload['savepath']) && $upload['code'] == 0) {
$upload = $this->buildFileUrl($upload);
return ['code' => 1, 'data' => $upload, 'msg' => '成功'];
}
$check = $uploadManager->checkFile($fileInfo);
//如果上传完成
if (isset($check['savepath']) && $check['code'] == 0) {
$check = $this->buildFileUrl($check);
return ['code' => 1, 'data' => $check];
} else {
$this->_error = "文件包不完整";
return ['code' => 0, 'data' => $check];
}
} catch (\Exception $e) {
$this->_error = $e->getMessage();
return ['code' => -1, 'data' => $e->getMessage()];
}
}
/**
* 处理文件
* 扩展包存在问题 ,考虑后续更新 尽量不更改扩展包,在这里做文件的处理
*/
public function buildFileUrl($data)
{
if (isset($data['savepath']) && $data['savepath'] != '') {
$conf = $this->config;
//获取除域名外的文件路径
$save_dir = $conf['disks'][$conf['default']['disk']]['save_dir'];
$file_path = str_replace($save_dir, '', $data['savepath']);
//拼接域名
$data['save_path'] = $conf['disks'][$conf['default']['disk']]['file_path'] . $file_path;
$data['file_path'] = $this->domain . $data['save_path'];
//删除多余的信息
unset($data['savepath']);
unset($data['code']);
}
return $data;
}
//检测文件上传大小
public function checkSize($file_size)
{
if ($file_size > $this->config['default']['maxSize']) {
return false;
}
return true;
}
/**检测文件类型
* @param $file_ext
* @return array|bool
*/
public function checkFileType($file_ext)
{ //获取配置信息
$extensions = $this->config['default']['extensions'];
//为空或者为 * 表示不过滤
if ($extensions == "" || $extensions == '*') {
return true;
}
//字符转换成数组
$exts = explode(',', $extensions);
if (in_array($file_ext, $exts)) {
$this->_error = "禁止上传该类型文件";
return ['code' => 0, 'data' => ''];
}
return true;
}
/**
* 检测文件分片情况
*/
public function checkFile($hash,$count){
$filePath = $this->config['disks'][$this->config['default']['disk']]['tmp_dir'] . $hash; //临时分片文件路径
// dump($filePath);
//检查分片是否存在
$chunkExists = [];
for ($index = 0; $index < $count; $index++) {
if (file_exists("{$filePath}_{$index}")) {
array_push($chunkExists, $index);
}
}
//分片有缺失,返回已存在的分片
$res['uploaded'] = $chunkExists;
return $res;
}
/**
* 删除文件
* @param $path
*/
public function deleteFile($path){
$path = app()->getRootPath() . 'public'.$path;
if (file_exists($path)){
@unlink($path);
}
return true;
}
/**
* 返回报错
* @return string
*/
public function getError()
{
return $this->_error;
}
}