Aarrgghh!!

Remote Backup

Explanation

Maintaining a site through FTP is for the most part managable, but it does make backsup somewhat hard to deal with. I figured there should be a way to use zip.cfc by Webclarity to create a viable backup strategy. I wrapped a custom cfc around it to munge the input so that I could pull down an zip with my entire directory.

Turns out I could do it. I was able to create a cfc that takes various exceptions and inclusions and can recursively roll through the directory structure to create a zip of an entire remote site.

Please note that this does require zip.cfc from Webclarity.



Sample Usage

Calling this code:

		


1: <cfinvoke component="backup" method="toZip" returnvariable="result" >
2: 	<cfinvokeargument name="directoryBackup" value="<fileroot>\wwwroot\terry" />
3: 	<cfinvokeargument name="zipOutput" value="<fileroot>\wwwroot\images\backup.zip" />
4: 	<cfinvokeargument name="extenstions_included" value="css" />
5: 	<cfinvokeargument name="recurse" value="TRUE" />
6: </cfinvoke>
7: 
8: <cfdump var="#result#">


Will return:

FILECOUNT16
RUNNINGTIME7480
FILEDETAILS
FILENAMEPATHINZIPSUCCESS
E:\webs\numtopia.com\wwwroot\terry\blog\styles-site.css\blogtrue
E:\webs\numtopia.com\wwwroot\terry\css\Copy of screen.css\csstrue
E:\webs\numtopia.com\wwwroot\terry\css\handheld.css\csstrue
E:\webs\numtopia.com\wwwroot\terry\css\master.css\csstrue
E:\webs\numtopia.com\wwwroot\terry\css\print.css\csstrue
E:\webs\numtopia.com\wwwroot\terry\css\screen.css\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\Copy of screen.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\handheld.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\master.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\master2.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\print.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\screen.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\static\css\screen2.css\static\csstrue
E:\webs\numtopia.com\wwwroot\terry\styles\ie7.css\stylestrue
E:\webs\numtopia.com\wwwroot\terry\styles\screen.css\stylestrue
E:\webs\numtopia.com\wwwroot\terry\styles\screenUncompressed.css\stylestrue
ZIPDETAILS
DATELASTMODIFIEDDIRECTORYNAMESIZE
{ts '2008-10-12 04:42:05'}E:\webs\numtopia.com\wwwroot\terry\imagesbackup.zip20876

and

backup.zip

Code

Source

		


1: <cfcomponent hint="Uses zip.cfc to create a backup file of a remote website.">
2: <!--- Please note that this does require zip.cfc from Webclarity http://www.webclarity.com/developers/zip.cfm --->
3: 	<cffunction access="public" name="toZip" output="false" returntype="struct" description="Backs up files to a zip file based on input parameters.">
4: 		<cfargument name="directoryBackup" type="string" required="yes" hint="Directory to Backup." />
5: 		<cfargument name="zipOutput" type="string" required="yes" hint="Absolute Path of the ouput zip filename." />
6: 		<cfargument name="compression" type="numeric" required="no" default="9" hint="compression Level" />
7: 		<cfargument name="extenstions_excluded" type="string" required="no" default="" hint="Comma delimited list of extenstions to Exclude." />
8: 		<cfargument name="extenstions_included" type="string" required="no" default="" hint="Comma delimited list of extenstions to which to restrict inclusion." />
9: 		<cfargument name="directories_excluded" type="string" required="no" default="" hint="Comma delimited list of firectory to Exclude" />
10: 		<cfargument name="directories_included" type="string" required="no" default="" hint="Comma delimited list of directory to which to restrict inclusion." />
11: 		<cfargument name="files_excluded" type="string" required="no" default="" hint="Comma delimited list of files to Exclude" />
12: 		<cfargument name="files_included" type="string" required="no" default="" hint="Comma delimited list of files to which to restrict inclusion." />
13: 		<cfargument name="recurse" type="boolean" required="no" default="FALSE" hint="Whether or not to recurse through the directory." />
14: 	
15: 		<!--- Massage query parameters. --->
16: 		<cfset arguments.extenstions_excluded =ListQualify(arguments.extenstions_excluded,"'") />
17: 		<cfset arguments.extenstions_included =ListQualify(arguments.extenstions_included,"'") />
18: 		<cfset arguments.directories_excluded =ListQualify(arguments.directories_excluded,"'") />
19: 		<cfset arguments.directories_included =ListQualify(arguments.directories_included,"'") />
20: 		<cfset arguments.files_excluded =ListQualify(arguments.files_excluded,"'") />
21: 		<cfset arguments.files_included =ListQualify(arguments.files_included,"'") >
22: 		
23: 		<!--- Set Default Return Parameters --->
24: 		<cfset result.fileCount= 0 />
25: 		<cfset result.filedetails = QueryNew("filename, pathinzip, success") />
26: 		<cfset result.runningTime= 0>
27: 		
28: 		<!--- Note start time  --->
29: 		<cfset startTime=getTickCount() />
30: 		
31: 		<!--- Get directory information --->
32: 		<cfdirectory directory="#arguments.directoryBackup#" action="list" name="fileList" recurse="#arguments.recurse#" />
33: 		
34: 		<cfset extenstionArray=ArrayNew(1)>
35: 		
36: 		<!--- Add extention information to query. --->	
37: 		<cfloop query="fileList">
38: 			<cfif FindNoCase(".", name)>
39: 				<cfset extenstionArray[CurrentRow]=ReplaceNoCase(Right(name[CurrentRow],3),".", "", "ALL") />
40: 			<cfelse>
41: 				<cfset extenstionArray[CurrentRow]="" />
42: 			</cfif>
43: 		</cfloop>
44: 
45: 		<cfset QueryAddColumn(fileList, "extenstion", extenstionArray) />
46: 		
47: 		<!--- Prune the query --->
48: 		<cfquery name="fileList" dbtype="query">
49: 			select 	*
50: 			from 	fileList
51: 			where	type = 'File'
52: 			<cfif Len(arguments.extenstions_excluded)>
53: 			and 	extenstion not in (#PreserveSingleQuotes(arguments.extenstions_excluded)#) 
54: 			</cfif>
55: 			<cfif Len(arguments.extenstions_included)>
56: 			and 	extenstion in (#PreserveSingleQuotes(arguments.extenstions_included)#) 
57: 			</cfif>
58: 			<cfif Len(arguments.directories_excluded)>
59: 			and 	directory not in (#PreserveSingleQuotes(arguments.directories_excluded)#) 
60: 			</cfif>
61: 			<cfif Len(arguments.directories_included)>
62: 			and 	directory in (#PreserveSingleQuotes(arguments.directories_included)#) 
63: 			</cfif>
64: 			<cfif Len(arguments.files_excluded)>
65: 			and 	name not in (#PreserveSingleQuotes(arguments.files_excluded)#) 
66: 			</cfif>
67: 			<cfif Len(arguments.directories_included)>
68: 			and 	name in (#PreserveSingleQuotes(arguments.files_included)#) 
69: 			</cfif>
70: 				
71: 		</cfquery>
72: 		
73: 		<!--- Convert record count to result output --->		
74: 		<cfset result.fileCount= fileList.RecordCount>
75: 		
76: 		<!--- Initialize Zip Object --->
77: 		<cfobject type="component" name="zipObj" component="zip" />
78: 		<cfinvoke component="#zipObj#" method="newZip">
79: 			<cfinvokeargument name="zipFileAndPath" value="#arguments.zipOutput#" />
80: 		</cfinvoke>
81: 		<!--- Set the compression level  --->
82: 		<cfinvoke component="#zipObj#" method="setCompression">
83: 			<cfinvokeargument name="compressionLevel" value="#arguments.compression#" />
84: 		</cfinvoke>
85: 				
86: 		<cfloop query="fileList">
87: 			<!--- Massage path in zip file --->
88: 			<cfset directory_in_zip= ReplaceNoCase(directory, arguments.directoryBackup, "", "ALL") />
89: 			
90: 			<!--- Add file to zip --->
91: 			<cfinvoke component="#zipObj#" method="addFile" returnvariable="success">
92: 				<cfinvokeargument name="fileAndPathToAdd" value="#directory#\#name#" />
93: 				<cfinvokeargument name="fileNameToStore" value="#name#" />
94: 				<cfinvokeargument name="pathToStore" value="#directory_in_zip#\" />
95: 			</cfinvoke> 
96: 			
97: 			<!--- Add results to query.  --->
98: 			<cfset QueryAddRow(result.filedetails) />
99: 			<cfset QuerySetCell(result.filedetails, "filename", "#directory#\#name#") />
100: 			<cfset QuerySetCell(result.filedetails, "pathinzip", "#directory_in_zip#") />
101: 			<cfset QuerySetCell(result.filedetails, "success", success) />
102: 		</cfloop>
103: 				
104: 		<!---  Create the zip file --->
105: 		<cfset zipObj.createZip() />
106: 		
107: 		<!--- Note end time  --->
108: 		<cfset endTime=getTickCount() />
109: 		<cfset result.runningTime= endTime - startTime />
110: 		
111: 		<!--- Retrieve zip file info --->
112: 		<cfdirectory directory="#GetDirectoryFromPath(zipOutput)#" action="list" name="result.ZIPDETAILS" recurse="no" filter="#GetFileFromPath(zipOutput)#" />
113: 	
114: 	
115: 		<cfreturn result />
116: 	</cffunction>
117: 
118: </cfcomponent>