在寫這個功能的時候借鑒了諸多系統,例如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);
}
}
}