<?php

namespace Chenlin2103\Controller;

class BaksqlController extends MainController{

public $config = '';                                                        //相关配置
    public $model = '';                                                         //实例化一个model
    public $content;                                                            //内容
    public $dbName = '';                                                        //数据库名
    public $dir_sep = '/';                                                      //路径符号

//初始化数据

function __construct() {
        parent::__construct();
        header("Content-type: text/html;charset=utf-8");
        set_time_limit(0);                                                      //不超时
        ini_set('memory_limit','500M');
        $this->config = array(
            'path' => C('DB_BACKUP'),                                           //备份文件存在哪里
            'isCompress' => 0,                                                  //是否开启gzip压缩      【未测试】
            'isDownload' => 0                                                   //备份完成后是否下载文件 【未测试】
        );
        $this->dbName = C('DB_NAME');                                           //当前数据库名称
        $this->model = new \Think\Model();
        //$sql = 'set interactive_timeout=24*3600';                             //空闲多少秒后 断开链接
        //$this->model>execute($sql);
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 已备份数据列表
     * +------------------------------------------------------------------------
     */

function index() {
        $tableRs = $this->model->query("SHOW CREATE TABLE `wh_news`");  
        dump($tableRs[0]);
        exit();
        $path = $this->config['path'];
        $fileArr = $this->MyScandir($path);
        foreach ($fileArr as $key => $value) {
            if ($key > 1) {
                //获取文件创建时间
                $fileTime = date('Y-m-d H:i:s', filemtime($path . '/' . $value));
                $fileSize = filesize($path . '/' . $value) / 1024;
                //获取文件大小
                $fileSize = $fileSize < 1024 ? number_format($fileSize, 2) . ' KB' :
                        number_format($fileSize / 1024, 2) . ' MB';
                //构建列表数组
                $list[] = array(
                    'name' => $value,
                    'time' => $fileTime,
                    'size' => $fileSize
                );
            }
        }
        dump($list);
        exit();
        $this->assign('list', $list);
        $this->display();
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 获取数据表
     * +------------------------------------------------------------------------
     */

function tablist() {
        $list = $this->model->query("SHOW TABLE STATUS FROM {$this->dbName}");  //得到表的信息
        //echo $Backup->getLastSql();
        
        $this->assign('list', $list);
        $this->display();
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 备份整个数据库
     * +------------------------------------------------------------------------
     */

function backall() {
        $tables = $this->getTables();
       
        if ($this->backup($tables)) {
            exit();
            $this->success('数据库备份成功!', 'index');
        } else {
            $this->error('数据库备份失败!');
        }
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 按表备份,可批量
     * +------------------------------------------------------------------------
     */

function backtables() {
        $tab = $_REQUEST['tab'];
        if (is_array($tab))
            $tables = $tab;
        else
            $tables[] = $tab;
        if ($this->backup($tables)) {
            if (is_array($tab))
                $this->success('数据库备份成功!');
            else
                $this->success('数据库备份成功!', '/public/ok');
        } else {
            $this->error('数据库备份失败!');
        }
    }

//还原数据库
    function recover() {
        if ($this->recover_file($_GET['file'])) {
            echo "ok";
            exit();
            $this->success('数据还原成功!', '/public/ok');
        } else {
            $this->error('数据还原失败!');
        }
    }

//删除数据备份
    function deletebak() {
        if (unlink($this->config['path'] . $this->dir_sep . $_GET['file'])) {
            $this->success('删除备份成功!', '/public/ok');
        } else {
            $this->error('删除备份失败!');
        }
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 下载备份文件
     * +------------------------------------------------------------------------
     */

function downloadBak() {
        $file_name = $_GET['file'];
        $file_dir = $this->config['path'];
        if (!file_exists($file_dir . "/" . $file_name)) { //检查文件是否存在
            return false;
            exit;
        } else {
            $file = fopen($file_dir . "/" . $file_name, "r"); // 打开文件
            // 输入文件标签
            header('Content-Encoding: none');
            header("Content-type: application/octet-stream");
            header("Accept-Ranges: bytes");
            header("Accept-Length: " . filesize($file_dir . "/" . $file_name));
            header('Content-Transfer-Encoding: binary');
            header("Content-Disposition: attachment; filename=" . $file_name);  //以真实文件名提供给浏览器下载
            header('Pragma: no-cache');
            header('Expires: 0');
            //输出文件内容
            echo fread($file, filesize($file_dir . "/" . $file_name));
            fclose($file);
            exit;
        }
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 获取 目录下文件数组
     * +------------------------------------------------------------------------
     * * @ $FilePath 目录路径
     * * @ $Order    排序
     * +------------------------------------------------------------------------
     * * @ 获取指定目录下的文件列表,返回数组
     * +------------------------------------------------------------------------
     */

private function MyScandir($FilePath = './', $Order = 0) {
        $FilePath = opendir($FilePath);
        while ($filename = readdir($FilePath)) {
            $fileArr[] = $filename;
        }
        $Order == 0 ? sort($fileArr) : rsort($fileArr);
        return $fileArr;
    }

/*     * ******************************************************************************************** */

/* -
     * +------------------------------------------------------------------------
     * * @ 读取备份文件
     * +------------------------------------------------------------------------
     * * @ $fileName 文件名
     * +------------------------------------------------------------------------
     */

private function getFile($fileName) {
        $this->content = '';
        $fileName = $this->trimPath($this->config['path'] . $this->dir_sep . $fileName);
        echo  $fileName ;
        if (is_file($fileName)) {
            $ext = strrchr($fileName, '.');
            if ($ext == '.sql') {
                
                $this->content = file_get_contents($fileName);
                
            } elseif ($ext == '.gz') {
                $this->content = implode('', gzfile($fileName));
            } else {
                $this->error('无法识别的文件格式!');
            }
        } else {
            $this->error('文件不存在!');
        }
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 把数据写入磁盘
     * +------------------------------------------------------------------------
     */

private function setFile() {
        $recognize = '';
        $recognize = $this->dbName;
        $fileName = $this->trimPath($this->config['path'] . $this->dir_sep . $recognize . '_' . date('YmdHis') . '_' . mt_rand(100000000, 999999999) . '.sql');
        $path = $this->setPath($fileName);
        if ($path !== true) {
            $this->error("无法创建备份目录目录 '$path'");
        }
        if ($this->config['isCompress'] == 0) {
            if (!file_put_contents($fileName, $this->content, LOCK_EX)) {
                $this->error('写入文件失败,请检查磁盘空间或者权限!');
            }
        } else {
            if (function_exists('gzwrite')) {
                $fileName .= '.gz';
                if ($gz = gzopen($fileName, 'wb')) {
                    gzwrite($gz, $this->content);
                    gzclose($gz);
                } else {
                    $this->error('写入文件失败,请检查磁盘空间或者权限!');
                }
            } else {
                $this->error('没有开启gzip扩展!');
            }
        }
        if ($this->config['isDownload']) {
            $this->downloadFile($fileName);
        }
    }

private function trimPath($path) {
        return str_replace(array('/', '\\', '//', '\\\\'), $this->dir_sep, $path);
    }

private function setPath($fileName) {
        $dirs = explode($this->dir_sep, dirname($fileName));
        $tmp = '';
        foreach ($dirs as $dir) {
            $tmp .= $dir . $this->dir_sep;
            if (!file_exists($tmp) && !@mkdir($tmp, 0777))
                return $tmp;
        }
        return true;
    }

//未测试
    private 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');
        header('Content-Length: ' . filesize($fileName));
        header('Content-Disposition: attachment; filename=' . basename($fileName));
        readfile($fileName);
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 给字符串添加 ` `
     * +------------------------------------------------------------------------
     * * @ $str 字符串
     * +------------------------------------------------------------------------
     * * @ 返回 `$str`
     * +------------------------------------------------------------------------
     */

private function backquote($str) {
        return "`{$str}`";
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 获取数据库的所有表
     * +------------------------------------------------------------------------
     * * @ $dbName  数据库名称
     * +------------------------------------------------------------------------
     */

private function getTables($dbName = '') {
        if (!empty($dbName)) {
            $sql = 'SHOW TABLES FROM ' . $dbName;
        } else {
            $sql = 'SHOW TABLES ';
        }
        $result = $this->model->query($sql);
        $info = array();
        foreach ($result as $key => $val) {
            $info[$key] = current($val);
        }
        return $info;
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 把传过来的数据 按指定长度分割成数组
     * +------------------------------------------------------------------------
     * * @ $array 要分割的数据
     * * @ $byte  要分割的长度
     * +------------------------------------------------------------------------
     * * @ 把数组按指定长度分割,并返回分割后的数组
     * +------------------------------------------------------------------------
     */

private function chunkArrayByByte($array, $byte = 5120) {
        $i = 0;
        $sum = 0;
        $return = array();
        foreach ($array as $v) {
            $sum += strlen($v);
            if ($sum < $byte) {
                $return[$i][] = $v;
            } elseif ($sum == $byte) {
                $return[++$i][] = $v;
                $sum = 0;
            } else {
                $return[++$i][] = $v;
                $i++;
                $sum = 0;
            }
        }
        return $return;
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 备份数据 { 备份每张表、视图及数据 }
     * +------------------------------------------------------------------------
     * * @ $tables 需要备份的表数组
     * +------------------------------------------------------------------------
     */

private function backup($tables) {
        if (empty($tables))
            $this->error('没有需要备份的数据表!');
//        $this->content = '/* This file is created by MySQLReback ' . date('Y-m-d H:i:s') . ' */';
        foreach ($tables as $i => $table) {
            $table = $this->backquote($table);   
            //为表名增加 ``
           echo "正在备份的表".$table."<br/>";
            $tableRs = $this->model->query("SHOW CREATE TABLE {$table}");       //获取当前表的创建语句
//            if (empty($tableRs[0]["create table"])) {
//              
//                //$this->content .= "\r\n /* 创建视图结构 {$table}  */";
//              
//            }
            if (!empty($tableRs[0]["create table"])) {
                //$this->content .= "\r\n /* 创建表结构 {$table}  */";
                 $this->content .= "\r\n DROP TABLE IF EXISTS {$table};"."/* MySQLReback Separation */";
                $this->content .=$tableRs[0]["create table"].";"."/* MySQLReback Separation */";
                $this->content .= "\r\n TRUNCATE TABLE {$table};"."/* MySQLReback Separation */";
             
                $tableDateRow = $this->model->query("SELECT * FROM {$table}");
                $valuesArr = array();
                $values = '';
                if (false != $tableDateRow) {
                    foreach ($tableDateRow as &$y) {
                        foreach ($y as &$v) {
                           if ($v=='')                                  //纠正empty 为0的时候  返回tree
                                $v = 'null';                                    //为空设为null
                            else
                                $v = "'" . mysql_escape_string($v) . "'";       //非空 加转意符
                        }
                        $valuesArr[] = '(' . implode(',', $y) . ')';
                    }
                }
                $temp = $this->chunkArrayByByte($valuesArr);
                if (is_array($temp)) {
                    foreach ($temp as $k=>$v) {
                        $values = implode(',', $v).";/* MySQLReback Separation */";
                        if ($values != ';/* MySQLReback Separation */') {
                              echo "正在备份表".$table."的第几条数据".$k."<br/>";
                            //$this->content .= "\r\n /* 插入数据 {$table} */";
                            $this->content .= "\r\n INSERT INTO {$table} VALUES {$values}";
                        }
                    }
                }
//                dump($this->content);
//                exit;
            }
            echo "备份完成!";
        }

if (!empty($this->content)) {
           
            $this->setFile();
        }
        return true;
    }

/* -
     * +------------------------------------------------------------------------
     * * @ 还原数据
     * +------------------------------------------------------------------------
     * * @ $fileName 文件名
     * +------------------------------------------------------------------------
     */

private function recover_file($fileName) {
        $this->getFile($fileName);
        
        if (!empty($this->content)) {
            $content = explode(';/* MySQLReback Separation */', $this->content);          
            foreach ($content as $i => $sql) {
                $sql = trim($sql);
                if (!empty($sql)) {
                    $mes = $this->model->execute($sql);
                    if (false === $mes) {                                       //如果 null 写入失败,换成 ''
                        $table_change = array('null' => '\'\'');
                        $sql = strtr($sql, $table_change);
                        $mes = $this->model->execute($sql);
                        
                    }
                    if (false === $mes) {                                       //如果遇到错误、记录错误
                        $log_text = '以下代码还原遇到问题:';
                        $log_text.="\r\n $sql";
                        set_log($log_text);
                    }
                }
            }
        } else {
          
            $this->error('无法读取备份文件!');
        }
   
        return true;
    }

}

tp备份数据的更多相关文章

  1. sql server中备份数据的几种方式

    当我们在写sql脚本要对数据表中的数据进行修改的时候,为了防止破坏数据,通常在开发前都会对数据表的数据进行备份,当我们sql脚本开发并测试完成后,再把数据恢复回来. 目前备份数据,我常用的方法有以下几 ...

  2. 更换Oracle备份数据文件

    应用背景:需要查看和修改一下Interlib中的数据,所以要反复的将备份数据进行导入和清空.整理一下步骤 删除tablespace drop tablespace interlib including ...

  3. Linux(Centos)全自动异地备份数据(WEB+Mysql)

    文章开始之前,先问下各位站长一个问题:什么东西对于站长是十分重要的?其实对于站长而言,很多东西都是很重要的.但我们现在排除外在因素,把范围缩小到网站系统本身,哪些是非常重要的呢?网站数据就是其中之一了 ...

  4. rsync命令(同步/备份数据)

    rsync命令rsync命令是一个远程数据同步工具,可通过 lam/wan快速同步多台主机间的文件.rsync使用所谓的 "rsync算法"来使用本地和远程两个主机之间的文件达到同 ...

  5. ORACLE用户管理方式下备份数据和复制数据库

    首先要明确的是,oracle数据库的备份可以分为逻辑备份和物理备份.           逻辑备份的是通过数据导出对数据进行备份,主要方式有老式的IMP/EXP和数据泵灯方式.适合变化较少的数据库,而 ...

  6. SQL SERVER 2008 R2 自动备份并删除过期备份数据

        我们的系统维护的过程中肯定需要对数据库进行定期的备份,但是如果定时手工备份的话,不但浪费时间,也不能保证每次都可以按时备份,所以自动备份成为了我们的不二选择,但是定时备份需要定期清理备份文件, ...

  7. 利用fputcsv导出数据备份数据

    今天,分享一个利用fputcsv导出数据备份数据的方法,我也时看到些零零散散的代码,想着拼起来,所以我只提供些思路,以及简单的代码,至于怎么组合能够让它更强大,尽情去探索吧 讲之前先上一段获取数据库里 ...

  8. 本文讲述下windows下使用rsync备份数据

    本文讲述下windows下使用rsync备份数据 需要使用的软件如下: 环境需求: 上海monitor上跑有定时任务计划备份线上数据库,现在需要把上海monitor上的备份数据拉回到179.12数据回 ...

  9. Fundebug是这样备份数据的

    摘要: 数据还是要备份的,万一删库了呢? 本文代码仓库: fundebug-mongodb-backup 引言 今年8月,腾讯云竟然把客户前沿数据的数据弄没了,Fundebug在第一时间进行了一些简单 ...

随机推荐

  1. CF Round #551 (Div. 2) D

    CF Round #551 (Div. 2) D 链接 https://codeforces.com/contest/1153/problem/D 思路 不考虑赋值和贪心,考虑排名. 设\(dp_i\ ...

  2. Python内置进制转换函数(实现16进制和ASCII转换)

    在进行wireshark抓包时你会发现底端窗口报文内容左边是十六进制数字,右边是每两个十六进制转换的ASCII字符,这里使用Python代码实现一个十六进制和ASCII的转换方法. hex() 转换一 ...

  3. 2019 ICPC南昌邀请赛 网络赛 K. MORE XOR

    说明 \(\oplus x​\)为累异或 $ x^{\oplus(a)}​$为异或幂 题意&解法 题库链接 $ f(l,r)=\oplus_{i=l}^{r} a[i]$ $ g(l,r)=\ ...

  4. jupyter notebook——安装配置

    本地登陆 cmd输入下面的命令,会进入用户主目录 jupyter notebook 在浏览器打开时,提示输入token,复制命令行上的token还是不能进入,其实浏览器上有提示的,按照提示操作即可,输 ...

  5. 什么是,session、cookies、token

    在一片文章上看到关于cookies和session 的解释,大概意思是这样的. 说你去星巴克喝咖啡,你平均一星期去两次,你的操作是看菜单,点咖啡.结账 加入你三星期不去,店员也许不及得你了,你依旧需要 ...

  6. 使用 Laragon 在 Windows 中快速搭建 Laravel 本地开发环境 (转)

    laravel学院 简介 对于那些使用 Windows 操作系统的同学来说,Homestead 和 LaraDock 虽说支持 Windows 系统,但是对初学者来说,安装配置起来还是有一定复杂度的, ...

  7. MySQL ERROR 1130 (HY000): Host '192.168.1.8' is not allowed to connect to this MySQL server

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.1.8' IDENTIFIED BY 'www.linuxidc.com' WITH GRANT OPTI ...

  8. js的call和apply区别

    call和apply都是改变了this的指针. obj.call(newObj, arg1, arg2, ...); obj.apply(newObj, [arg1, arg2, ...]); 上面的 ...

  9. vs2015 c# winfrom应用程序打包成64位

    关于Winform打包过程在网上已有详细教程,参考:https://www.cnblogs.com/yinsq/p/5254893.html 此次工作中需要打包成64位的程序,网上没有查到方法,现在讲 ...

  10. RS485转USB插电脑上通讯不上

    在确定没有其他问题时,基本可以确定是干扰问题,换个24V电源试试,不要用原来的线 485接口确定,好坏通过两个相反对接,发送信息,两边一致,就可以