在写这个功能的时候借鉴了诸多系统,例如dedeCMS,phpCMS等系统,可惜如出一辙,都有bug,他们没办法很好的控制住分卷的大小,所以自己冥思苦想,最总有了一下思路:
//如果要轉載本文請注明出處,免的出現版權紛爭,我不喜歡看到那種轉載了我的作品卻不注明出處的人 Seven{See7di#Gmail.com}
$work=StrToLower(_r($_GET["work"]));
Switch ($work){
Case "export":
_Export();
Break;
Case "exportloop":
_ExportLoop();
Break;
Case "tozip":
_Tozip();
Break;
}
/*---------------------------------*/
Function _Export(){
Global $Mysql,$work;
$f1=_r($_GET["f1"]);
//如果是第一个回圈
IF($f1=="1"){
//首先获取一次是否指定了备份表
$tables=$_REQUEST["tables"];
Echo ($tables);
IF(Empty($tables)){
//得到数据表
$Result=$Mysql->View("Show Tables From ".BLK_SysDbname."");
Foreach($Result as $val){
$tables[]=$val[0];
}
}Else{
$tables=Explode(",", $tables);
$tables=Array_Filter($tables,'_nul');
}
$_SESSION['Tab'] = $tables;
//初始化数据表表序号
$nList=0;
//初始化文件序号
$nFile=1;
//用来做比较,看看是否已经写入建表信息
$_SESSION['nList'] = ($nList-1);
}Else{
$nList=_r($_GET["nList"]);
$nFile=_r($_GET["nFile"]);
}
$iSql = ''; //抓取的内容
$fPath = "Cache/"; //保存目录
$cName = "DB_Export.sql"; //缓存文件
$_Tab = $_SESSION['Tab'][$nList]; //当前所操作的表
$fName = "DB".Date('_md_').$nFile.".sql";
//判断目录状况
IF(!Is_writable($fPath)){Exit("数据无法备份到服务器!请检查 ".$fPath." 目录是否可写。");}
//判断是否备份完毕
IF(Count($_SESSION['Tab'])<=$nList){
@Unlink($fPath.$cName);
For($i=1;$i<=$nFile;$i++){
$FileArr[]=$fPath."DB".Date('_md_').$i.".sql";
}
$_FileName="DB".Date('_md').".zip";
Tozip($FileArr,$_FileName,2,2);
Alert("","?work=backdb&rback=1");
Die();
}
//每次读一个表,得到头信息和建表信息
IF($_SESSION['nList'] < $nList){
IF($nFile==1 And $nList==0){
//删除文件
For($i=1;$i<1000;$i++){
IF(File_exists($fPath."DB".Date('_md_').$i.".sql")){
@Unlink($fPath."DB".Date('_md_').$i.".sql");
}Else{
Break;
}
}
//建立文件
File_put_contents($fPath.$fName,"");
File_put_contents($fPath.$cName, "");
$iSql = "# Create by ".BLK_SysName."\n# Create time ".Date('Y-m-d')."\n# Mysql Version ".$Mysql->Version()."\n# PHP Version ".@phpversion()."\n# --------------------------------------------------------\n\nSET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";\n";
}
$iSql .= "DROP TABLE IF EXISTS `".$_Tab."`;\n";
$_iSql = Mysql_fetch_row(mysql_query("SHOW CREATE TABLE ".$_Tab.""));
$iSql .= $_iSql[1].";\n\n";
}
//写入头信息
$iSql=Trim(File_get_contents($fPath.$fName)."\n\n".$iSql);
File_put_contents($fPath.$fName,$iSql);
//得到缓存的内容并判断是否为空,如果为空,抓取当前表所有的内容放入缓存
$_Cache=Trim(File_get_contents($fPath.$cName));
IF(Empty($_Cache)){
$_Cache=DropInfo($_Tab);
File_put_contents($fPath.$cName,$_Cache);
}
//循环抓取,直到备份文件满额为止(因为循环不能及时得到文件尺寸)
Alert("","?work=exportloop&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
}
/*---------------------------------*/
Function _ExportLoop(){
Global $work;
$nList=_r($_GET["nList"]);
$nFile=_r($_GET["nFile"]);
$iSql = ''; //抓取的内容
$fPath = "Cache/"; //保存目录
$fSize = (BLK_SysDbsplit*1024); //文件大小,2048K=2M
$fName = "DB".Date('_md_').$nFile.".sql";
$cName = "DB_Export.sql";
//显示进度
Echo "<br><br><strong>备份正在进行中请稍候,现在正在生成 <span style='color:red;'>".$fName."</span></strong><br><br>";
Echo "<br>".(FileSize($fPath.$fName))."<br>".$fSize."<br><br>";
Echo Loading((FileSize($fPath.$fName)),$fSize);
//如果备份文件满了
IF(((FileSize($fPath.$fName))+9000)>$fSize){
$nFile++; //备份文件序号加一
$_SESSION['nList'] = $nList; //防止再次写入建表信息
Alert("","?work=export&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",30);
}Else{
//取得现在缓存的内容,编译为数组
$_Cache = (File($fPath.$cName));
//为备份文件抓取需要的数据,每次4条
$_Info=Array();
For($i=0;$i<2;$i++){
$_Info[]=$_Cache[$i];
}
//得到新的缓存数据
$_Cache=array_diff_key($_Cache,$_Info);
File_put_contents($fPath.$cName,Trim(Implode("",$_Cache)));
//重新整理备份文件的内容并写入
$iSql=Trim(File_get_contents($fPath.$fName))."\n".Trim(Implode("",$_Info));
File_put_contents($fPath.$fName,$iSql);
//如果备份文件未满而缓存空了,则进入下一个表
IF(Count($_Cache)<1){
$nList++;
$_SESSION['nList'] = ($nList-1);
Alert("","?work=export&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
//如果备份文件未满而缓存未空,则循环该函数
}Else{
Alert("","?work=exportloop&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
}
}
}