ColdFusion TIPS PLUS
Issue 00086 http://www.cftipsplus.com
I. My CommentsII. ColdFusion In Context: Use CFFTP
By R. Martin Ladner
martin.ladner@knology.net
I. Comments:
I have a new sponsor that will be showing up soon at the bottom of my
ezine. Take a look at it. I think it is an awesome product. The site
will help you see how easy it is to use.
Now that I have got you interest... You will have to wait to see what
new ad it is....
I am almost out of boxes... moving is a pain... I have not yet joined
the User Group here in New Orleans but I am making plans to be there.
As long as I own www.cftipsplus.com it will be FREE. So please keep in
mind I have to find ways to make money to keep it FREE. Everyone keep
in touch and I hope you all had good holidays.
Keep Coding,
Nathan Stanford
President/CEO
C.F. Concepts, Inc.
http://www.coldfusionmonthly.com
http://www.cftipsplus.com
If you have suggestions for articles send them to us.
If you would like to write for cftipsplus.com
send us an email to:
admin@cftipsplus.com
IF YOU WANT TO BE AN AUTHOR SEND IN YOUR COLDFUSION TIPS.
Remember this is a great way to get your name known in the
ColdFusion Community.
Advanced, Intensive ColdFusion Training!Visit this site. If you have plans to get training here is a company that provides Advanced, Intensive ColdFusion Training. Check them out.
http://www.coldfusiontraining.com/index.cfm?ref=cftipsplus
CFM - The ColdFusion Monthly!
http://www.ColdFusionMonthly.com
By becoming a .CFM subscriber, you'll receive. ColdFusion information you will not find anywhere else:
Tips, tricks, techniques, strategies, and a wealth of knowledge you will be able to apply immediately to your work, all from established developers.
Monthly access to new articles written by industry-leading ColdFusion experts. A fully-functional application that accompanies each issue.
Full access to all issues, past and present (with a one year paid subscription). The chance to be seen in our "Community Spotlight" corner, which showcases new writers and emerging talent
If you have any suggestions please email me at
cftips@nsnd.com.
II. ColdFusion in Context: Use CFFTP
By R. Martin Ladner
martin.ladner@knology.net
Suppose you wanted to pull and display files from a machine that doesn't
have a Web server loaded. One way to do that is with the cfftp tag. This
tip lets you view a local directory with cfdirectory, delete local files
with cffile, view a remote directory with cfftp, copy files from that
directory with cfftp, and display them javascript to pop open a new
window.
Outline the Viewer
Here's an outline to follow to juggle all these tasks. Put the pop-up
script in the document header so it will be ready when you need it.
Invoke session management as one way to give the ftp connection a unique
name that no other user will step all over while you're using it. When
the user presses a submit button on the form, you'll need to test for
that variable and act on it before the form reloads. To give the user
feedback and controls, you'll need to query the remote and local
directories. You'll need to use the queries to embed directory lists and
file controls into the form. Finally, the display buttons will need to
be set to invoke the javascript routine you placed in the header.
Pop-Up
Nest script tags within an HTML header and place the pop-up function
within that. The word "page" is a placeholder for the value to be passed
by form controls for display. Begin "view.cfm" with this code.
<head>
<script language="javascript">
function pop(page) {
popWindow = window.open(page, 'popWin');
}
</script>
</head>
Establish Defaults
Open the body and session, and set common defaults; add this code to
view.cfm. The application name can be anything not repeated elsewhere on
your server. Load login information from an included file. This way, if
the Web server hiccups and tries to serve the unterpreted content of
view.cfm, the login information won't be seen. To simplify installation,
set the "scriptdir" to the full drive and directory path leading to this
page.
<body>
<cfapplication name="ftp" sessionmanagement="yes">
<cfinclude template="howtoftp.cfm">
<cfset scriptdir=getDirectoryFromPath(#cgi.cf_template_path#)>
Open and Act
Set key form variables if undefined, open the session, and act; add this
code to view.cfm. If the user asked to copy a file from the remote
server, change remote directories and get the file. If the user asked to
delete a file from the local server, delete the file.
<cfparam name="form.myget" default="">
<cfparam name="form.mydel" default="">
<cfinclude template="ropen.cfm">
<cfif len(form.myget)>
<cfinclude template="rcd.cfm">
<cfinclude template="rget.cfm">
<cfelseif len(form.mydel)>
<cfinclude template="ldel.cfm">
</cfif>
Build a Form and Close the Connection
Query remote directories, close the ftp connection, and build a form
based on the queries. Add this code to view.cfm. The directory-seeking
code will be in rls.cfm and ldir.cfm. The form has three different kinds
of controls: a submit button (used for refresh) that doesn't set
anything important, submit buttons that pass a filename for copy
("myget") or delete ("mydel"), and button buttons [grin] that display a
file ("myshow") in a window through the use of the javacript routine
invoked earlier.
To place the files in context, information about the files (such as
their date and size) is shown. The information for both remote and local
directories is accessed as one would access a database query. However,
the names and data types for some of this information varies depending
on the source. The date and time of a file in the remote directory is a
real date object that has to be parsed for display; the corresponding
element for the local directory is a string already, and it doesn't have
the same name. The file size is called Length for the remote query and
Size for the local query. Finally, to avoid seeing names such as . and
.. in the local display, they're filtered out with a contains statement.
Close the body of the document.
<cfinclude template="rls.cfm">
<cfinclude template="rclose.cfm">
<cfinclude template="ldir.cfm">
<form name="view" action="view.cfm" method="post">
<input name="lookagain" type="submit" value="Refresh">
<p>
REMOTE DIRECTORY<br>
Copy of these from the remote server.<br>
<cfoutput query="remotedir">
Copy - <input name="myget" type="submit" value="#Name#">,
#DateFormat(LastModified,"mm/dd/yyyy")#
#TimeFormat(LastModified,"hh:mm:ss tt")#,
#Length#<br>
</cfoutput>
<p>
LOCAL DIRECTORY<br>
Display or delete one of these from the local server.<br>
<cfoutput query="localdir">
<cfif ".." does not contain Name>
Display - <input name="myshow" type="button"
value="#Name#" onClick="javascript:pop('stuff/#Name#');">,
#DateLastModified#, #Size# - <input name="mydel" type="submit"
value="#Name#"> - Delete<br>
</cfif>
</cfoutput>
</form>
</body>
Set Login Data
Populate the following variables with real data; call this code
howtoftp.cfm
<cfset request.server="MyFtpServerNameOrIP">
<cfset request.username="MyUsername">
<cfset request.password="MyPassword">
<cfset request.workdir="RemoteDirRelativeToLogin">
Open the Connection
The cfftp tag lets you open and name a connection that you can then
re-use with other ftp commands until the remote server times breaks it.
Enabling session management as you did in the calling page made it
possible to use the sessionID as the connection name. (You could use the
createuuid function instead to get a unique name and then use a hidden
form field to pass it alone if you planned to use the same connection
for subsequent pages.) In coding the open statement, set a timeout, let
it try a few times, and set stoponerror to no so it its errors won't
halt the page. If it doesn't succeed, let cfftp tell you why with
cfftp.errortext. Name this code ropen.cfm
<cfftp connection="#session.sessionID#" action="open"
server="#request.server#"
username="#request.username#" password="#request.password#"
timeout="30" retrycount="3" stoponerror="no">
<cfif cfftp.errorcode is not 0>
The connection did not succeed;
<cfoutput>#cfftp.errortext#</cfoutput>
<cfabort>
<cfelse>
Connected OK.
</cfif>
Change Remote Directories
While the connection is still open, you can perform multiple ftp
operations without logging in again. Thus, the login information doesn't
have to be specified over again for changing a directory right away.
Call this code rcd.cfm.
<cfftp connection="#session.sessionID#" action="changedir"
directory="#request.workdir#"
timeout="30" retrycount="3" stoponerror="no">
<cfif cfftp.errorcode is not 0>
<cfoutput>Directory not changed to #request.workdir#:
#cfftp.errortext#
</cfoutput>
<cfabort>
<cfelse>
<cfoutput>Changed directory to #request.workdir#</cfoutput>
</cfif>
Get a File
For the get function, both the remote file and the name it will have on
the local server must be specified. The transfer mode is set explicitly
here for clarity, but cfftp will usually make the right choice based on
file extension anyway (and its default list of extensions with which
ASCII mode should be used is easily changed). Call this code rget.cfm.
<cfftp connection="#session.sessionID#" action="getfile"
remotefile="#form.myget#" localfile="#scriptdir#/stuff/#form.myget#"
transfermode="binary"
timeout="30" retrycount="3" stoponerror="no" failifexists="no">
<cfif cfftp.errorcode is not 0>
<cfoutput>
Attempt to get #form.myget# failed.
#cfftp.errortext#
</cfoutput>
<cfelse>
Got <cfoutput>#form.myget#</cfoutput> OK.
</cfif>
<cfset form.myget="">
Delete a Local File
The command to delete a local file is actually a one-liner that's pulled
out into a separate file for clarity. The file parameter consists of the
path to the script (set by view.cfm), the directory below it that holds
these files, and the name of the file. Call this code ldel.cfm.
<cffile action="delete"
file="#scriptdir#/stuff/#mydel#">
Query a Remote Directory
The action to query a remote directory produces a query that you can use
in the same manner as a database query. Reference the name parameter
used here as the name of the query. Call this code rls.cfm.
<cfftp connection="#session.sessionID#" action="listdir"
directory="#request.workdir#" name="remotedir" timeout="30"
retrycount="3" stoponerror="no">
<cfif cfftp.errorcode is not 0>
Remote listing did not succeed.
<cfoutput>
#cfftp.errortext#
</cfoutput>
<cfelse>
Remote listing was OK.
</cfif>
Close a Remote Connection
If you don't close the connection, it will tie up resources of two
computers until the remote server eventually times it out. Call this
code rclose.cfm.
<cfftp connection="#session.sessionID#"
action="close">
Query a Local Directory
The action to query a remote directory produces a query that you can use
in the same manner as a database query. Reference the name parameter
used here as the name of the query. Call this code ldir.cfm.
<cfdirectory action="list" directory="#scriptdir#/stuff"
name="localdir">
Try Out the Demo
To make this work, you'll need directories on two servers and this code.
Put some pictures in the remote directory and correct this code to match
that directory name. Put this code on your local server, add a directory
below it, and correct this code to match the local directory name. Then
click on view.cfm. Get some files (copies) from the remote server,
display them locally, and delete local copies.
Findings
The ftp protocol is tough to test when you don't own your own servers.
In general, I had good results with list, get, and delete. All my put
attempts resulted in zero-length files (which is why I didn't use "put"
in the demo), but that was probably due to firewall and permission
issues. The cfftp tag is otherwise easy and straightforward to use.
=Marty=
Publisher and Creator:
Nathan Stanford,
admin@cftipsplus.com
C.F. Concepts, Inc.
http://www.cftipsplus.com
Macromedia and ColdFusion are U.S. registered trademarks.
Copyright (c) 2000 - 2001 C.F. Concepts, Inc.
CFTIPSPLUS.COM and NSND.COM
Permission is granted to circulate this publication via
MANUAL forwarding by email to friends provided that the text is
forwarded in its entirety and no fee is charged.