diff --git a/app/home/controller/Database.php b/app/home/controller/Database.php index 7b6d992..de4577d 100644 --- a/app/home/controller/Database.php +++ b/app/home/controller/Database.php @@ -11,171 +11,211 @@ namespace app\home\controller; use app\base\BaseController; use backup\Backup; +use think\facade\Session; use think\facade\Db; use think\facade\View; class Database extends BaseController { - protected $db = '', $datadir; - public function initialize() + //数据表列表 + public function database() { - parent::initialize(); - $this->config = array( - 'path' => './backup/', // 数据库备份路径 - 'part' => 20971520, // 数据库备份卷大小 - 'compress' => 0, // 数据库备份文件是否启用压缩 0不压缩 1 压缩 - 'level' => 9, // 数据库备份文件压缩级别 1普通 4 一般 9最高 - ); - $this->db = new Backup($this->config); - } - - // 数据列表 - public function database() - { - if (request()->isAjax()) { - // 数据信息 - $list = $this->db->dataList(); - // 计算总大小 - $total = 0; - foreach ($list as $k => $v) { - $total += $v['data_length']; - $list[$k]['data_size'] = $v['data_length']; - $list[$k]['data_length'] = format_bytes($v['data_length']); + if (request()->isAjax()) { + // 数据信息 + $db = new Backup(); + $list = $db->dataList(); + // 计算总大小 + $total = 0; + foreach ($list as $k => $v) { + $total += $v['data_length']; + $list[$k]['data_size'] = $v['data_length']; + $list[$k]['data_length'] = format_bytes($v['data_length']); + } + // 提示信息 + $dataTips = '数据库中共有 ' . count($list) . ' 张表,共计 ' . format_bytes($total) . '大小。'; + $data['data'] = $list; + return table_assign(0, $dataTips, $data); + } + return view(); + } + + //备份数据 + public function backup() + { + $db= new Backup(); + if(request()->isPost()){ + $tables=get_params('tables'); + $fileinfo =$db->getFile(); + //检查是否有正在执行的任务 + $lock = "{$fileinfo['filepath']}backup.lock"; + if(is_file($lock)){ + return to_assign(2, '检测到有一个备份任务未完成'); + } else { + //创建锁文件 + file_put_contents($lock,time()); } - // 提示信息 - $dataTips = '数据库中共有 ' . count($list) . ' 张表,共计 ' . format_bytes($total) . '大小。'; - $data['data'] = $list; - return table_assign(0, $dataTips, $data); - } - return view(); - } - - // 备份 - public function backup() - { - $tables = get_params('id'); - if (!empty($tables)) { - $tables = explode(',', $tables); - foreach ($tables as $table) { - $this->db->setFile()->backup($table, 0); + // 检查备份目录是否可写 + if(!is_writeable($fileinfo['filepath'])){ + return to_assign(1, '备份目录不存在或不可写,请检查后重试!'); } - add_log('bak'); - return to_assign(0, '备份成功!'); - } else { - return to_assign(1, '请选择要备份的表'); - } - } + + //缓存锁文件 + Session::set('lock', $lock); + //缓存备份文件信息 + Session::set('backup_file', $fileinfo['file']); + //缓存要备份的表 + Session::set('backup_tables', $tables); + //创建备份文件 + if(false !== $db->Backup_Init()){ + return to_assign(0, '初始化成功',['tab'=>['id' => 0, 'start' => 0,'table'=>$tables[0]]]); + }else{ + return to_assign(1, '初始化失败,备份文件创建失败!'); + } + }else if(request()->isGet()){ + $tables = Session::get('backup_tables'); + $file=Session::get('backup_file'); + $id=get_params('id'); + $start=get_params('start'); + $start= $db->setFile($file)->backup($tables[$id], $start); + if(false === $start){ + return to_assign(1, '备份出错!'); + }else if(0 === $start){ + if(isset($tables[++$id])){ + return to_assign(0, '备份完成',['tab'=>['id' => $id, 'start' => 0,'table'=>$tables[$id-1]]]); + } else { //备份完成,清空缓存 + unlink(Session::get('lock')); + Session::delete('backup_tables'); + Session::delete('backup_file'); + add_log('bak'); + return to_assign(0, '备份完成',['tab'=>['start' => 'ok','table'=>$tables[$id-1]]]); + } + } + }else{ + return to_assign(1, '参数错误!'); + } + } - // 优化 - public function optimize() - { - $tables = get_params('id'); - if (empty($tables)) { - return to_assign(0, '请选择要优化的表'); + //优化表 + public function optimize($tables= null) + { + $db= new Backup(); + //return to_assign(0, $db->optimize($tables)); + if($db->optimize($tables)){ + add_log('optimize'); + return to_assign(0, '数据表优化完成'); + }else{ + return to_assign(1, '数据表优化出错请重试'); } - $tables = explode(',', $tables); - if ($this->db->optimize($tables)) { - add_log('optimize'); - return to_assign(0, '数据表优化成功!'); - } else { - return to_assign(1, '数据表优化出错请重试'); - } - } - - // 修复 - public function repair() - { - $tables = get_params('id'); - if (empty($tables)) { - return to_assign(1, '请选择要修复的表'); - } - $tables = explode(',', $tables); - if ($this->db->repair($tables)) { - add_log('repair'); - return to_assign(0, '数据表修复成功'); - } else { - return to_assign(1, '数据表修复出错请重试'); - } - } - - // 还原列表 - public function backuplist() - { - // 数据信息 - $list = $this->db->fileList(); - $listNew = []; - $indx = 0; + } + + //修复表 + public function repair($tables= null) + { + $db= new Backup(); + //return to_assign(0, $db->repair($tables)); + if($db->repair($tables)){ + add_log('repair'); + return to_assign(0, '数据表修复完成'); + }else{ + return to_assign(1, '数据表修复出错请重试'); + } + } + + + //备份文件列表 + public function backuplist() + { + $db= new Backup(); + $list = $db->fileList(); + $fileinfo =$db->getFile(); + $lock = "{$fileinfo['filepath']}backup.lock"; + $lock_time = 0; + if(is_file($lock)){ + $lock_time = file_get_contents($lock); + } + $listNew = []; + $indx = 0; foreach ($list as $k => $v) { $listNew[$indx]['time'] = $k; - $listNew[$indx]['data'][] = $v; + $listNew[$indx]['timespan'] = $v['time']; + $listNew[$indx]['data'] = $v; $indx++; - // $listNew[$k]['list'] = $list[$k]; } $list = $listNew; array_multisort(array_column($list, 'time'), SORT_DESC, $list); - return view('', ['list' => $list]); - } - - // 执行还原数据库操作 - public function import(int $id) - { - $list = $this->db->getFile('timeverif', $id); - $this->db->setFile($list)->import(1); - add_log('reduction'); - return to_assign(0, '还原成功!'); - } - - // 下载 - public function downfile(string $name) - { - $file_name = $name; //得到文件名 - header("Content-type:text/html;charset=utf-8"); - $file_name = iconv("utf-8", "gb2312", $file_name); // 转换编码 - $file_sub_path = $this->config['path']; //确保文件在这个路径下面,换成你文件所在的路径 - $file_path = $file_sub_path . $file_name; - # 将反斜杠 替换成正斜杠 - $file_path = str_replace('\\', '/', $file_path); - if (!file_exists($file_path)) { - $this->error($file_path);exit; //如果提示这个错误,很可能你的路径不对,可以打印$file_sub_path查看 - } - $fp = fopen($file_path, "r"); // 以可读的方式打开这个文件 - # 如果出现图片无法打开,可以在这个位置添加函数 - ob_clean(); # 清空擦掉,输出缓冲区。 - $file_size = filesize($file_path); - //下载文件需要用到的头 - Header("Content-type: application/octet-stream"); - Header("Accept-Ranges: bytes"); - Header("Accept-Length:" . $file_size); - Header("Content-Disposition: attachment; filename = " . $file_name); - $buffer = 1024000; - $file_count = 0; - while (!feof($fp) && $file_count < $file_size) { - $file_con = fread($fp, $buffer); - $file_count += $buffer; - echo $file_con; - } - fclose($fp); //关闭这个打开的文件 - } - - // 删除sql文件 - public function del(string $id) - { - if (request()->isAjax()) { - if (strpos($id, ',') !== false) { - $idArr = explode(',', $id); - foreach ($idArr as $k => $v) { - $this->db->delFile($v); + return view('',['list'=>$list,'lock_time' => $lock_time]); + } + + //数据还原 + public function import($time = 0, $part = null, $start = null) + { + $db= new Backup(); + $time =(int)$time; + if(is_numeric($time) && is_null($part) && is_null($start)){ + $list = $db->getFile('timeverif',$time); + if(is_array($list)){ + Session::set('backup_list', $list); + return to_assign(0, '初始化完成',array('part' => 1, 'start' => 0,'time' => $time)); + }else{ + return to_assign(1, '备份文件可能已经损坏,请检查'); + } + }else if(is_numeric($part) && is_numeric($start)){ + $list=Session::get('backup_list'); + $part =(int)$part; + $start =(int)$start; + $start= $db->setFile($list)->import($start,$time,$part); + if(false===$start){ + return to_assign(1, '还原数据出错,请重试'); + }elseif(0 === $start){ + if(isset($list[++$part])){ + $data = array('part' => $part, 'start' => 0,'time' => $time); + return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面",$data); + } else { + Session::delete('backup_list'); + return to_assign(0, '还原数据成功'); } - add_log('delete'); - return to_assign(0, "删除成功"); - } - if ($this->db->delFile($id)) { - add_log('delete'); - return to_assign(0, "删除成功"); - } else { - return to_assign(1, "备份文件删除失败,请检查文件权限"); - } - } - } - -} + }else{ + $data = array('part' => $part, 'start' => $start[0],'time' => $time); + if($start[1]){ + $rate = floor(100 * ($start[0] / $start[1])); + return to_assign(0, "正在还原...卷{$part} ({$rate}%),请勿关闭当前页面",$data); + } else { + $data['gz'] = 1; + return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面",$data); + } + return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面"); + } + }else{ + return to_assign(1, "参数错误"); + } + } + /** + * 删除备份文件 + */ + public function del($time = 0,$lock=0){ + $db= new Backup(); + if($lock==1){ + $fileinfo =$db->getFile(); + $lock = "{$fileinfo['filepath']}backup.lock"; + if(is_file($lock)){ + $time = file_get_contents($lock); + unlink($lock); + } + } + if($db->delFile((int)$time)){ + add_log('delete'); + return to_assign(0, '删除成功'); + }else{ + return to_assign(0, '删除失败,请检查权限'); + } + } + /** + * 下载备份文件 + */ + public function downfile($time = 0,$part=0){ + $db= new Backup(); + add_log('down'); + $db->downloadFile((int)$time,$part-1); + } + +} \ No newline at end of file diff --git a/app/home/view/database/backuplist.html b/app/home/view/database/backuplist.html index 92598b7..08b08d0 100644 --- a/app/home/view/database/backuplist.html +++ b/app/home/view/database/backuplist.html @@ -5,10 +5,10 @@
文件名称 | -分卷 | -文件大小 | 文件格式 | 分隔符 | +文件总大小 | +分卷总数 | 操作 |
---|---|---|---|---|---|---|---|
备份时间:{$vo.time} | -|||||||
- {:date("Ymd",$voo.time)}{$voo.compress}{:date("His",$voo.time)}{$voo.compress}{$voo.part}.sql - | -{$voo.part} | -{:format_bytes($voo.size)} | +备份时间:{$vo.time}{if $vo.timespan == $lock_time}该备份不是完整备份,请删除重新备份{/if} | .sql | -{$voo.compress} | -- | |
+ {:date("Ymd",$vo.timespan)}{$vo.data.compress}{:date("His",$vo.timespan)}{$vo.data.compress}{$i+1}.sql + | ++ 下载备份(分卷{$i+1}) + | +