支持SAE的数据库备份Thinkphp3.2.3

浏览:1585 发布日期:2016/05/08 分类:功能实现 关键字: SAE SAE数据库备份 数据库备份 备份
数据库备份是一个好看的功能,支持SAE的数据库备份的类库
// +----------------------------------------------------------------------
// | 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 次 )

评论( 相关
后面还有条评论,点击查看>>