
// +----------------------------------------------------------------------
// | Author: 左边 (加群:366504956(刚建,欢迎) 交流thinkphp下微信开发)
// +----------------------------------------------------------------------
//类库放在Application\Common\Libs目录下
use \Common\Libs\MySQLReback;
//数据备份
public function sqlback(){
$DataDir = "Databak";
if(!file_exists($DataDir))mkdir($DataDir) ;
$opt = trim(I('get.opt'));
$file = trim(I('get.file'));
$mr = new MySQLReback();
$mr->setDBName(C('DB_NAME'));
$mr->setPath($DataDir);
if ($opt) {
if ($opt == 'backup') {
$mr->backup()?$alert = '数据库备份成功!':$alert = $mr->error();
}
if($opt == 'optimize'){
$mr->optimize()?$alert = '数据库优化成功!':$alert = $mr->error();
}
if ($opt == 'redo' && $file) {
$r = $mr->recover($file);
$alert = '数据库还原成功'.$r['qty'] ."条";
}
if ($opt== 'del' && $file) {
$mr->remove($file)?$alert = '数据库删除成功!':$alert = $mr->error();
}
if ($opt == 'download' && $file ) $mr->DownloadFile($file);
}
$lists = $mr->dataList($DataDir);
$this->assign("list", $lists);
if($alert)
$this->assign('alert',"alert('".$alert."');");
$this->display();
}页面<extend name="Public/default"/>
<block name="jscss">
<script type="text/javascript">
$(function(){
$('.opt').click(function(){
opt = $(this).data('opt');
file = $(this).parent().data('f');
location.href = "__ACTION__/opt/"+opt+'/file/'+file;
})
{$alert}
})
</script>
</block>
<block name="top_left">系统管理 > 数据库管理</block>
<block name="content">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="top" class="td_n pdl10 pdr10 pdt10">
<table width="100%" border="0" cellpadding="0" cellspacing="0" class="table_1">
<tr class="tr_t">
<td width="80" class="td_l_c">编号</td>
<td class="td_l_c">文件名</td>
<td width="180" class="td_l_c">备份时间</td>
<td width="100" class="td_l_c">文件大小</td>
<td width="180" class="td_l_c">操作</td>
</tr>
<volist name="list" id="vo">
<tr class="tr">
<td class="td_l_c title">
{$key+1}
</td>
<td class="td_l_c" data-f="{$vo.filename}">
<a href="#" class="opt" data-opt="download">{$vo.filename}</a>
</td>
<td class="td_l_c">
{$vo.filetime}
</td>
<td class="td_l_c">
{:$vo['filesize']/1000} KB
</td>
<td class="td_l_c" data-f="{$vo.filename}">
<input type="button" data-opt="redo" class="button_edit opt" value="还原">
<input type="button" data-opt="download" class="button_edit opt" value="下载">
<input type="button" data-opt="del" class="button_del opt" value="删除">
</td>
</tr>
</volist>
<tr class="tr_t">
<td class="td_l_l" colspan="5" data-f="1">
<input type="submit" data-opt="backup" class="button_Submit opt" value="备份"> <input type="submit" data-opt="optimize" class="button_button opt" value="优化">
</td>
</tr>
</table>
</td>
</tr>
</table>
</block>类文件<?php
// +----------------------------------------------------------------------
// | Author: 左边 (加群:366504956(刚建,欢迎) 交流thinkphp下微信开发)
// +----------------------------------------------------------------------
namespace Common\Libs;
use Think\Db;
use sinacloud\sae\Storage as Storage;
class MySQLReback {
private $path;
private $isCompress;
private $content;
private $dbName;
private $error;
private $sign = '/*++$*/';
const DIR_SEP = DIRECTORY_SEPARATOR;
public function __construct() {
$this->path = 'Databak';
}
public function setDBName($dbName) {
$this->dbName = $dbName;
}
public function setPath($path) {
$this->path = $path;
}
public function setIsCompress($isCompress){
$this->isCompress = $isCompress;
}
private function getFile($fileName) {
if(strtolower(STORAGE_TYPE) == 'sae'){
$s = new Storage();
$r = json_encode($s -> getObject(strtolower( $this->path ), $fileName) );
$r = json_decode($r,true);
return $r['body'];
}
$fileName = $this->path . self::DIR_SEP . $fileName;
if (is_file($fileName)) {
$ext = strrchr($fileName, '.');
if ($ext == '.sql') {
return file_get_contents($fileName);
} elseif ($ext == '.gz') {
return implode('', gzfile($fileName));
} else {
$this->error = '_无法识别的文件格式!';
return;
}
} else {
$this->error = '文件不存在!';
return;
}
}
private function setFile($content) {
$recognize = $this->dbName;
$fileName = $recognize . '_' . date('YmdHis') . '_' . mt_rand(100000000, 999999999) . '.sql';
if(strtolower(STORAGE_TYPE) == 'sae'){
$s = new Storage();
$root_path = strtolower($this->$path);
//不存在就创建
$pathArr = $s->listBuckets();
if(!in_array($root_path,$pathArr) ){
$s->putBucket($root_path,'.r:*');
}
//写入
$path = $s->putObject($content, $root_path, $fileName);
if($path !== true){
$this->error = "写入文件失败";
return;
}
return $path;
}
$fileName = $this->path . self::DIR_SEP .$fileName;
$path = $this->cetPath($fileName);
if ($path !== true) {
$this->error = "无法创建备份目录,目录 '$path'";
return;
}
if ($this->isCompress == 0) {
if (!file_put_contents($fileName, $content, LOCK_EX)) {
$this->error = '写入文件失败,请检查磁盘空间或者权限!';
return;
}
} else {
if (function_exists('gzwrite')) {
$fileName .= '.gz';
$gz = gzopen($fileName, 'wb');
if ($gz) {
$gw = gzwrite($gz, $content);
gzclose($gz);
return $gw;
} else {
$this->error = '写入文件失败,请检查磁盘空间或者权限!';
return;
}
} else {
$this->error = '没有开启gzip扩展!';
return;
}
}
}
private function cetPath($fileName) {
$dirs = explode(self::DIR_SEP, dirname($fileName));
$tmp = '';
foreach ($dirs as $dir) {
$tmp .= $dir . self::DIR_SEP;
if (!file_exists($tmp) && !@mkdir($tmp, 0777))
return;
}
return true;
}
//备份
public function backup(){
$db = Db::getInstance();
$tables = $db->query('SHOW TABLE STATUS');
$tables = array_map('array_change_key_case', $tables);
$sql = '/* This file is created by MySQLReback ' . date('Y-m-d H:i:s') . ' */';
foreach ($tables as $value) {
$table = $value['name'];
$result = $db->query("SHOW CREATE TABLE `{$table}`");
$create = $result[0]['create table'];
$sql .= "\r\n /* 创建表结构 {$table} */";
$sql .= "\r\n DROP TABLE IF EXISTS {$table};". $this->sign ." {$create};" . $this->sign;
$result = $db->query("SELECT COUNT(*) AS count FROM `{$table}`");
$count = $result['0']['count'];
if($count){
$sql .= "\r\n /* 插入数据 {$table} */";
$result = $db->query("SELECT * FROM {$table}");
foreach ($result as $row) {
$row = array_map('addslashes', $row);
$sql .= "\r\n INSERT INTO {$table} VALUES ( '" . str_replace( array("\r","\n") , array('\r','\n') ,implode("', '", $row) ) . "' );".$this->sign;
}
}
}
if ($sql) {
return $this->setFile($sql);
}else{
$this->error = '数据为空';
}
return;
}
//删除备份
public function remove($fileName){
if(strtolower(STORAGE_TYPE) == 'sae'){
$s = new Storage();
$r = $s->deleteObject(strtolower($this->path), $fileName);
if(!$r){
$this->error = '删除失败';
return;
}
return true;
}
if(!@unlink($this->path . self::DIR_SEP . $fileName)){
$this->error = '删除失败';
return;
}
return true;
}
//表优化
public function optimize(){
if(strtolower(STORAGE_TYPE) == 'sae'){
$this->error='SAE数据库不支持表优化';
return ;
}
$db = Db::getInstance();
$list = $db->query('SHOW TABLE STATUS');
$list = array_map('array_change_key_case', $list);
foreach ($list as $key => $value) {
$tables[] = $value['name'];
}
if($tables) {
if(is_array($tables)){
$tables = implode('`,`', $tables);
$list[] = $db->execute("OPTIMIZE TABLE `{$tables}`");
}
}
return $list;
}
//恢复
public function recover($fileName) {
$content = $this->getFile($fileName);
if (!$content) {
if($this->error)return;
return '数据为空';
}
$content = explode($this->sign, $content);
$db = Db::getInstance();
foreach ($content as $i => $sql) {
$sql = trim($sql);
if (!empty($sql)){
$res = $db->execute($sql);
if($res){
$rs['qty']++;
}else{
$rt[] = $sql;
}
}
}
$rs['error'] = $rt;
return $rs;
}
public function DownloadFile($fileName) {
ob_end_clean();
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
if(strtolower(STORAGE_TYPE) == 'sae'){
$s = new Storage();
$r = json_encode($s -> getObject(strtolower( $this->path ), $fileName) );
$r = json_decode($r,true);
header('Content-Disposition: attachment; filename="' . $fileName . '"');
echo $r['body'];
}else{
$fileName = $this->path . self::DIR_SEP . $fileName;
$stat = stat($this->path . self::DIR_SEP . $filename);
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . $stat['size']);
readfile($fileName);
}
}
public function dataList() {
if(strtolower(STORAGE_TYPE) == 'sae'){
$s = new Storage();
$f = $s->getBucket( strtolower($this->path) );
foreach ($f as $v) {
$rt['filename'] = $v['name'];
$rt['filetime'] = date('Y-m-d H:i:s',strtotime($v['last_modified']) );
$rt['filesize'] = $v['bytes'];
$FileAndFolderAyy[] = $rt;
}
}else{
$FilePath = opendir($this->path);
while (false !== ($filename = readdir($FilePath))) {
if ($filename!="." && $filename!=".."){
$stat = stat($this->path .'/'. $filename);
$rt['filename'] = $filename;
$rt['filetime'] = date('Y-m-d H:i:s', $stat['mtime'] );
$rt['filesize'] = $stat['size'];
$FileAndFolderAyy[] = $rt;
}
}
}
$Order == 0 ? sort($FileAndFolderAyy) : rsort($FileAndFolderAyy);
return $FileAndFolderAyy;
}
public function error(){
return $this->error;
}
}
?>
MySQLReback.class.zip
( 2.71 KB 下载:123 次 )
