One guy's take on the web, programming, cigars, politics, Philadelphia, and whatever else comes to mind.
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.
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:
| FILECOUNT | 9 | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RUNNINGTIME | 4616 | ||||||||||||||||||||||||||||||
| FILEDETAILS |
|
||||||||||||||||||||||||||||||
| ZIPDETAILS |
|
and
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>