php版微信多客服务API开发-添加、更新、上传、删除

 更新时间:2016年11月25日 16:16  点击:1718
php版微信多客服务API开发-添加、更新、上传、删除功能我们演示的是php版本的一个功能,下面一起来看看整个开发过程与例子。
看到微信API文档加入了多客服务接口,就想着把它的功能集成到本站的WP微信插件里,开发过程中因为文档的误导,真是坑人不小的,微信就不能写文档认真点么?不过总归最后得到解决,先看下效果图:
wechat-post-customer

 

添加一个多客服帐号,还可以上传头像哦
wechat-post-add-customer

 

下面是官方文档坑人的API 截图:
uploadheader

 

如上图,开始自己留意到http://开头是错误的,但万万没想到,自己核对过参数和API的url都没错的情况下,居然给我报48001 即API没有被授权!我就郁闷,我用多客服的其他add 、update、del接口都没问题,怎么这个上传upload头像就没授权呢?
无奈之下找微信官方客服,一番令人无语的问答后,最终解决了!原来是API的URL上的/customservice/kfacount/中的kfaccount少了个c,真是操啊!!

 

以下代码只作参考,毕竟大家所写的方式不同,我的处理过程是,取到表单数据后,先提交给多客服的add接口,成功后,再upload头像,最后再写进数据库!流程处理的代码如下:

/*
     * 添加多客服帐号
     */
    public function add_customer() {
        $data = array();
        foreach($_POST['customer'] as $items ) {
            if( ! empty($items['value'])) {
                $key = $items['name'];
                $val = $items['value'];
                if($key == 'media_file') {
                    $img_url = $val;
                    continue;
                }
                if($key == 'password') {
                    $original_pass = $val;
                    $val = md5($val);
                }
                $data[$key] = $val;
            }
        }
        $res = $this->call('/kfaccount/add', $data, self::JSON, self::API_TYPE_SERVICE);
        if($res) {
            if($img_url) {
                $this->upload_customer_header($img_url, $data['kf_account']);
                $data['local_headimgurl'] = $img_url;
            }
            global $wpdb;
            $table = $wpdb->prefix.'wechat_customer';
            if( ! empty($original_pass)) $data['password'] = $original_pass;
            $wpdb->insert($table, array_merge($data, array('create_time' => time())));
            exit('ok');
        }
        exit('errcode: '.$this->_error_number.' errmsg: '.$this->_error);
    }
要改Wechat-JSON.php API类,新增多客服接口上传方法:
//上传多客服头像 必须是jpg格式,推荐640*640大小的图片以达到最佳效果
    public function CustomerHeaderUpload($file_full_path, $account = '') {
        $this->_access_token = $this->getAccessToken();
        $res = false;
        if ($this->_access_token) {
            $url = 'https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?';
            $url = $url.'access_token='.$this->_access_token.'&kf_account='.$account;
            $res = $this->request($url, array(
                'media' => '@'.$file_full_path,
            ), self::POST);
        }
        return $res;
    }

本文章为各位介绍一篇关于 php版微信JS-SDK音频接口的例子,如果你正在做微信开发功能用到了jssdk音频接口的话可以和小编来看看。


本想这个接口很简单不想写写的,因为看文档它跟图像接口差不多。不过给新用JS-SDK的朋友参照下也好。因为在群中有人说录音后不能转发给用户,经测试是完全可以的,只是时间显示上不对。显示1秒,但不影响播放长度。例子中,我用AJAX提交上传后的media_id,和写固定的open_id 传到后台,调用客服接口发出,注意48小时!这意味着将本地的localId转为serverId后,可以下传回自己服务器,因为微信服务器只保存3天,继续用TP作为框架。
首先是Layout\record.phtml:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link href="__PUBLIC__/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
{__CONTENT__}
</body>
<script type="text/javascript">
    window.jQuery || document.write("<script src='__PUBLIC__/js/jquery-1.10.2.min.js'>"+"<"+"/script>");
</script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
    wx.config({
        debug: false,
        appId: '{$signPackage["appId"]}',
        timestamp: {$signPackage["timestamp"]},
        nonceStr: '{$signPackage["nonceStr"]}',
        signature: '{$signPackage["signature"]}',
        jsApiList: [
            'checkJsApi',
            'startRecord',
            'stopRecord',
            'onVoiceRecordEnd',
            'playVoice',
            'pauseVoice',
            'stopVoice',
            'onVoicePlayEnd',
            'uploadVoice',
            'downloadVoice',
            'getNetworkType'
        ]
    });
    wx.ready(function () {
        var record = {
            localId: '',
            serverId: ''
        };
 
        wx.getNetworkType({
            success: function (res) {
                var networkType = res.networkType; // 返回网络类型2g,3g,4g,wifi
                jQuery(function() {
                    $('#networkType').html(networkType);
                });
            }
        });
 
        document.querySelector('#record').onclick = function () {
            $("#record h2").html('录音中...');
            wx.startRecord();
        };
 
        document.querySelector('#stoprecord').onclick = function() {
            wx.stopRecord({
                success: function (res) {
                    record.localId = res.localId;
                    $("#record h2").html('开始录音');
                }
            });
        };
 
        wx.onVoiceRecordEnd({
            complete: function (res) {
                record.localId = res.localId;
                $("#record h2").html('开始录音');
            }
        });
 
        wx.onVoicePlayEnd({
            success: function (res) {
                //record.localId = res.localId; // 返回音频的本地ID
                alert('播放完毕');
            }
        });
 
        document.querySelector('#playrecord').onclick = function() {
            if(record.localId == '') {
                alert('你还没录音');
                return;
            }
            wx.playVoice({
                localId: record.localId
            });
        };
 
        document.querySelector('#uploadrecord').onclick = function() {
            if(record.localId == '') {
                alert('你还没录音localId');
                return;
            }
            wx.uploadVoice({
                localId: record.localId,
                isShowProgressTips: 1,
                success: function (res) {
                    record.serverId = res.serverId;
                    $.getJSON('http://www.demo.com/tp/home/index/sendrecord',{openid:'oHdUGj7hZfJfr4ILMB5rgctpNrOw', media_id:record.serverId}, function(data) {
                        if(data)
                            alert('发送成功');
                    });
                }
            });
        };
 
        document.querySelector('#downloadrecord').onclick = function() {
            if(record.serverId == '') {
                alert('你还没上传录音');
                return;
            }
            wx.downloadVoice({
                serverId: record.serverId,
                isShowProgressTips: 1,
                success: function (res) {
                    record.localId = res.localId;
                    alert(record.localId);
                }
            });
        };
    });
 
    wx.error(function(res){
        var str = res.errMsg;
        var reg = /invalid signature$/;
        var r = str.match(reg);
        if(r !== null) {
            jQuery(function(){
                $.getJSON('http://www.demo.com/tp/home/index/ticket', function(data) {
                    if(data) {
                        alert('ticket update');
                        location = location;
                        window.navigate(location);
                    }
                });
            });
        }
    });
</script>
</html>
视图views\Index\record.phtml
<style>
    .text-center {text-align: center;}
    .btn-hight {height:100px;width:230px;}
    #img img{width:200px;}
</style>
<div class="col-lg-12 col-sm-12" style="margin: 12px auto 10px;">
    <div class="form-group text-center">
        <h2>你使用的网络类型是: <span id="networkType"></span></h2>
    </div>
    <div class="form-group text-center">
        <button id="record" type="button" class="btn btn-primary btn-hight"><h2>开始录音</h2></button>
    </div>
 
    <div class="form-group text-center">
        <button id="stoprecord" type="button" class="btn btn-warning btn-hight"><h2>停止录音</h2></button>
    </div>
 
    <div class="form-group text-center">
        <button id="playrecord" type="button" class="btn btn-primary btn-hight"><h2>播放录音</h2></button>
    </div>
 
    <div class="form-group text-center">
        <button id="pauserecord" type="button" class="btn btn-success btn-hight"><h2>暂停播放</h2></button>
    </div>
 
    <div class="form-group text-center">
        <button id="uploadrecord" type="button" class="btn btn-danger btn-hight"><h2>上传录音</h2></button>
    </div>
 
    <div class="form-group text-center">
        <button id="downloadrecord" type="button" class="btn btn-info btn-hight"><h2>下载录音</h2></button>
    </div>
</div>
Controller里就加入的方法:
    public function recordAction() {
        layout('Layout\record');
        $this->display();
    }
 
    public function sendrecordAction() {
        if(IS_AJAX) {
            $openid = I('openid','');
            $media_id = I('media_id','');
            $res = $this->api->call('/message/custom/send', array(
                'touser' => $openid,
                'msgtype' => 'voice',
                'voice' => array('media_id' => $media_id),
            ), WechatJSAPI::JSON);
            if($res)
                $this->ajaxReturn(true);
            $this->ajaxReturn(false);
        }
    }
录音效果图(第一次会弹出提示要授权)

 

录音效果图(第一次会弹出提示要授权)
record_voice
上传中效果图:
upload_voice
上传接着发客服消息效果图:
sendok_voice
最后在服务号看到的效果图(注意最长60秒,它都只显示1″,但不影响你录制时的长度播放)
send_voice

 

好了,有什么话要对我说,体验下,口下留情啊!
下面我们来看一篇关于php实现图片以base64显示的例子,希望文章能够让各位朋友可以实现字符串形式保存到网页从而不需要再加载图片了哦。

这是在RFC2397中定义的Data URI scheme,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入,比如上面那串字符,其实是一张图片,将这些字符复制黏贴到火狐的地址栏中并转到,就能看到了。

在上面的Data URI中,data表示取得数据的协定名称,image/jpeg是数据类型名称,base64是数据的编码方法,逗号后面就是这个image/jpeg文件base64编码后的数据。

目前Data URI scheme支持的类型有:

data:text/plain,文本数据
data:text/html,HTML代码
data:text/html;base64,base64编码的HTML代码
data:text/css,CSS代码
data:text/css;base64,base64编码的CSS代码
data:text/javascript,javascript代码
data:text/javascript;base64,base64编码的Javascript代码
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据


$img_file = 'https://img.alicdn.com/bao/uploaded/TB1eaiELpXXXXcPXpXXSutbFXXX.jpg';
$img_info = getimagesize($img_file);
$img_src  = "data:{$img_info['mime']};base64," . base64_encode(file_get_contents($img_file));
exit("<img src='{$img_src}' />");

php抽象类与接口的区别一般的朋友一下说不清楚具体有哪些区别了这里小编总结了一些关于php抽象类与接口的区别详细,具体的如下。


区别:

  1、对接口的使用是通过关键字implements。对抽象类的使用是通过关键字extends。当然接口也可以通过关键字extends继承。
  2、接口中不可以声明成员变量(包括类静态变量),但是可以声明类常量。抽象类中可以声明各种类型成员变量,实现数据的封装。(另JAVA接口中的成员变量都要声明为public static final类型)
  3、接口没有构造函数,抽象类可以有构造函数。

  4、接口中的方法默认都是public类型的,而抽象类中的方法可以使用private,protected,public来修饰。
  5、一个类可以同时实现多个接口,但一个类只能继承于一个抽象类。


抽象类还是接口。

  如果要创建一个模型,这个模型将由一些紧密相关的对象采用,就可以使用抽象类。如果要创建将由一些不相关对象采用的功能,就使用接口。
  如果必须从多个来源继承行为,就使用接口。
  如果知道所有类都会共享一个公共的行为实现,就使用抽象类,并在其中实现该行为

例子

<?php
abstract class Father {
 function meth1() {
  echo "meth1...<br>";
 }
 abstract function meth2();
 public $var1="var1";
 public static $var2="var2";
 const Var3="Var3";
}
class Son extends Father {
 function meth2() {
  echo "meth2 of Son...<br>";
 }
}
$s=new Son();
echo $s->var1."<br>";
echo Father::$var2."<br>";
echo Father::Var3."<br>";


Interface IFather {
 //public $iVar1="iVar1";        此处接口定义中不能包含成员变量
 //public static $iVar2="iVar2"; 此处接口定义中不能包含静态变量
 const iVar3="iVar3";
 function iMeth1();
}
Class ISon implements IFather {
 function iMeth1() {
  echo "iMeth1...<br>";
 }
}
$is=new ISon();
echo IFather::iVar3;
?>

如果更详细一点我们可以对每一个都介绍一下

抽象类:是基于类来说,其本身就是类,只是一种特殊的类,不能直接实例,可以在类里定义方法,属性。类似于模版,规范后让子类实现详细功能。

接口:主要基于方法的规范,有点像抽象类里的抽象方法,只是其相对于抽象方法来说,更加独立。可让某个类通过组合多个方法来形成新的类。

抽象类与接口的相同点:

1、都是用于声明某一种事物,规范名称、参数,形成模块,未有详细的实现细节。

2、都是通过类来实现相关的细节工作

3、语法上,抽象类的抽象方法与接口一样,不能有方法体,即{}符号

4、都可以用继承,接口可以继承接口形成新的接口,抽象类可以继承抽象类从而形成新的抽象类

抽象类与接口的不同点:

1、抽象类可以有属性、普通方法、抽象方法,但接口不能有属性、普通方法、可以有常量

2、抽象类内未必有抽象方法,但接口内一定会有“抽象”方法

3、语法上有不同

4、抽象类用abstract关键字在类前声明,且有class声明为类,接口是用interface来声明,但不能用class来声明,因为接口不是类。

5、抽象类的抽象方法一定要用abstract来声明,而接口则不需要

6、抽象类是用extends关键字让子类继承父类后,在子类实现详细的抽象方法。而接口则是用implements让普通类在类里实现接口的详细方法,且接口可以一次性实现多个方法,用逗号分开各个接口就可

各自的特点:

抽象类内未必有抽象方法,但有抽象方法的类,则必是抽象类

抽象类内,即便全是具体方法,也不能够实例化,只要新建类来继承后,实例继承类才可以

接口可以让一个类一次性实现多个不同的方法

接口本身就是抽象的,但注意不是抽象类,因为接口不是类,只是其方法是抽象的。所以,其也是抽象的

应用与结合:

以下的代码是基于自己的思考,未在实际开发中应用,只是这种写法有点奇特。让抽象与接口结合起来。

一、抽象类与接口的结合

<?php
/*
写此程序源于自己的猜测,想在抽象类里实现某一接口。
*/
interface work{
    public function say();
}
abstract class a implements work{
    public function showlove(){
        echo 'love you<br />';
    }
}
class b extends a{
    public function say(){
        echo 'hello, i m in b';
    }
}
$k=new b();
$k->say();
/*
以上程序能正常执行
普通类implements接口后,就变成了抽象类了,这就好像是直接给抽象类增加了一个抽象方法。
*/

二、接口与继承的结合

父类是普通类,子类继承后,同时在子类里实现接口。

疑问:这样的做法是否有意义,在实际开发中是否有这样的应用?

<?php
interface kk{
    public function say();
}
class a {
    public function show(){
        echo '我是父类<br />';
    }
}
class b extends a implements kk{
    public function say(){
        echo '我是继承A类,同时实现say接口的<br />';
    }

}
$b=new b();
$b->show();//我是父类
$b->say();//我是继承A类,同时实现say接口的

对于拟虚空间我们肯定没有操作服务器的权限此时要备份数据库我们可以集成在网站后台来操作,下面一起来看一篇关于PHP实现MySQL数据库备份的源码教程,具体的如下所示。

下面是一个php数据库备份的源代码,大家也可以根据自己的需求进行修改。

<?php
// 备份数据库
$host = "localhost";
$user = "root"; //数据库账号
$password = ""; //数据库密码
$dbname = "mysql"; //数据库名称
// 这里的账号、密码、名称都是从页面传过来的
if (!mysql_connect($host, $user, $password)) // 连接mysql数据库
{
 echo '数据库连接失败,请核对后再试';
    exit;
}
if (!mysql_select_db($dbname)) // 是否存在该数据库
{
 echo '不存在数据库:' . $dbname . ',请核对后再试';
    exit;
}
mysql_query("set names 'utf8'");
$mysql = "set charset utf8;\r\n";
$q1 = mysql_query("show tables");
while ($t = mysql_fetch_array($q1))
{
    $table = $t[0];
    $q2 = mysql_query("show create table `$table`");
    $sql = mysql_fetch_array($q2);
    $mysql .= $sql['Create Table'] . ";\r\n";
    $q3 = mysql_query("select * from `$table`");
    while ($data = mysql_fetch_assoc($q3))
    {
        $keys = array_keys($data);
        $keys = array_map('addslashes', $keys);
        $keys = join('`,`', $keys);
        $keys = "`" . $keys . "`";
        $vals = array_values($data);
        $vals = array_map('addslashes', $vals);
        $vals = join("','", $vals);
        $vals = "'" . $vals . "'";
        $mysql .= "insert into `$table`($keys) values($vals);\r\n";
    }
}
 
$filename = $dbname . date('Ymjgi') . ".sql"; //存放路径,默认存放到项目最外层
$fp = fopen($filename, 'w');
fputs($fp, $mysql);
fclose($fp);
echo "数据备份成功";
?>

如果使用的是thinkphp可以使用下面代码来备份mysql数据库

<?php
 // www.111cn.net
class BaksqlAction extends CommonAction {
 
    public $config = '';                                                        //相关配置
    public $model = '';                                                         //实例化一个model
    public $content;                                                            //内容
    public $dbName = '';                                                        //数据库名
    public $dir_sep = '/';                                                      //路径符号
 
    //初始化数据
 
    function _initialize() {
        parent::_initialize();
        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 Model();
        //$sql = 'set interactive_timeout=24*3600';                             //空闲多少秒后 断开链接
        //$this->model>execute($sql);
    }
 
    /* -
     * +------------------------------------------------------------------------
     * * @ 已备份数据列表
     * +------------------------------------------------------------------------
     */
 
    function index() {
        $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
                );
            }
        }
        $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)) {
            $this->success('数据库备份成功!', '/public/ok');
        } 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'])) {
            $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);
        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);                                  //为表名增加 ``
            $tableRs = $this->model->query("SHOW CREATE TABLE {$table}");       //获取当前表的创建语句
            if (!empty($tableRs[0]["Create View"])) {
                $this->content .= "\r\n /* 创建视图结构 {$table}  */";
                $this->content .= "\r\n DROP VIEW IF EXISTS {$table};/* MySQLReback Separation */ " . $tableRs[0]["Create View"] . ";/* MySQLReback Separation */";
            }
            if (!empty($tableRs[0]["Create Table"])) {
                $this->content .= "\r\n /* 创建表结构 {$table}  */";
                $this->content .= "\r\n DROP TABLE IF EXISTS {$table};/* MySQLReback Separation */ " . $tableRs[0]["Create 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 $v) {
                        $values = implode(',', $v) . ';/* MySQLReback Separation */';
                        if ($values != ';/* MySQLReback Separation */') {
                            $this->content .= "\r\n /* 插入数据 {$table} */";
                            $this->content .= "\r\n INSERT INTO {$table} VALUES {$values}";
                        }
                    }
                }
//                dump($this->content);
//                exit;
            }
        }
 
        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;
    }
 
}
?>

[!--infotagslink--]

相关文章

  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • 删除条目时弹出的确认对话框

    复制代码 代码如下: <td> <a href="/member/life/edit_ppt/<?php echo $v->id;?>" class="btn">编辑</a> <a href="javascript:;" onclick="if(confirm('您确定删除这条记录?')){location.href='/member/life/d...2014-06-07
  • Php文件上传类class.upload.php用法示例

    本文章来人大家介绍一个php文件上传类的使用方法,期望此实例对各位php入门者会有不小帮助哦。 简介 Class.upload.php是用于管理上传文件的php文件上传类, 它可以帮...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • jQuery实现简单的文件上传进度条效果

    本文实例讲述了jQuery实现文件上传进度条效果的代码。分享给大家供大家参考。具体如下: 运行效果截图如下:具体代码如下:<!DOCTYPE html><html><head><meta charset="utf-8"><title>upload</title><link rel="stylesheet...2015-11-24
  • php文件上传你必须知道的几点

    本篇文章主要说明的是与php文件上传的相关配置的知识点。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,下面一一说明。打开php.ini配置文件找到File Upl...2015-10-21
  • EXCEL数据上传到SQL SERVER中的简单实现方法

    EXCEL数据上传到SQL SERVER中的方法需要注意到三点!注意点一:要把EXCEL数据上传到SQL SERVER中必须提前把EXCEL传到服务器上.做法: 在ASP.NET环境中,添加一个FileUpload上传控件后台代码的E.X: 复制代码 代码如下: if...2013-09-23
  • php跨网站请求伪造与防止伪造方法

    伪造跨站请求介绍伪造跨站请求比较难以防范,而且危害巨大,攻击者可以通过这种方式恶作剧,发spam信息,删除数据等等。...2013-10-01
  • Centos中彻底删除Mysql(rpm、yum安装的情况)

    我用的centos6,mysql让我整出了各种问题,我想重装一个全新的mysql,yum remove mysql-server mysql之后再install并不能得到一个干净的mysql,原来的/etc/my.cnf依然没变,datadir里面的数据已没有任何变化,手动删除/etc/my.cn...2015-03-15
  • DWVA上传漏洞挖掘的测试例子

    DVWA (Dam Vulnerable Web Application)DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了SQL注入、XSS、盲注等常见的一些安全漏洞...2016-11-25
  • MyBatis-Plus的物理删除和逻辑删除(使用场景)

    数据库中的数据删除会分为两种:物理删除 和 逻辑删除,接下来通过本文给大家介绍MyBatis-Plus的物理删除和逻辑删除使用场景分析,感兴趣的朋友一起看看吧...2021-09-25
  • PHP swfupload图片上传的实例代码

    PHP代码如下:复制代码 代码如下:if (isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) { $upload_file = $_FILES['Filedata']; $fil...2013-10-04
  • 百度编辑器ueditor修改图片上传默认路径

    本案例非通用,仅作笔记以备用 修改后的结果是 百度编辑器里上传的图片路径为/d/file/upload1...2014-07-03
  • mybatis-plus getOne和逻辑删除问题详解

    这篇文章主要介绍了mybatis-plus getOne和逻辑删除,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-08-26
  • SpringMVC文件上传原理及实现过程解析

    这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
  • C#中添加窗口的步骤详解

    下面小编就为大家带来一篇C#中添加窗口的步骤详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • 借助FileReader实现将文件编码为Base64后通过AJAX上传

    这篇文章主要介绍了借助FileReader实现将文件编码为Base64后通过AJAX上传的方法,包括后端对文件数据解码并保存的PHP代码,需要的朋友可以参考下...2015-12-25
  • jQuery动态添加与删除tr行实例代码

    最近由于项目的需要,需要动态的添加和删除table中的tr,感觉用JS可以实现,但是在网上找了一下,单纯的自己写JS,感觉太麻烦,而且也不好维护。于是想到了最近学的jQuery。这篇文章给大家用实例介绍了jQuery动态添加与删除tr行的方法,有需要的朋友们可以参考借鉴。...2016-10-20
  • PHP的APC模块实现上传进度条

    APC模块,它的全称是Alternative PHP Cache。APC可以将所有PHP代码会被缓存起来, 另外它可提供一定的内存缓存功能.但是这个功能并不是十分完美,有报告说如果频繁使用APC缓存的写入功能,会导致不可预料的错误.如果想使用...2015-10-30