Nov 14, 2006
Posted On : 11/14/2006 at 11:20 PM | Posted By : Remote Synthesis
Related Categories:
ColdFusion
So I recently had the need to use cfftp functionality and decided to write a component wrapper for the functionality. The component (which can be downloaded via the download link below) wraps all the functions available in cfftp, making you code easier to read and far less verbose. It also handles some basic logic for you to further simplify some of the functions. I tested against a couple of connections and it worked nicely (with one exception I will discuss in a bit), however it doesn't support things like transferMode, passive or proxyServer at this point in time.So how do you use the component? The following code will establish a connection, get the contents of the root directory, create a new directory, change to that directory, upload a file to that directory and finally close the connection.
<cfset ftpService = createObject("component","ftpService").init("ftp.myserver.com","username","password") /> <cfset qryContents = ftpService.listDir() /> <cfset ftpService.createDir('mynewdir') /> <cfset ftpService.changeDir('mynewdir') /> <cfset ftpService.putFile('ftpService.cfc') /> <cfset ftpService.close() />
As you can see, the code is *much* cleaner and easier to understand than the alternative which is I think 6 cfftp calls.
Now what didn't work? Well, the remove action in cfftp handles removing files and directories, but it failed every time I tried to remove a directory even though I could validate it existed and was empty. I would either get the directory is not found or a permissions error depending on how I formatted the path. Since this is my first time actually using cfftp (never had the need before), I am hoping someone out there can help me figure out the problem.
Anyway, hopefully this will be useful to other folks. I will also be adding it to my projects page shortly. If people are using it and the functionality is requested, I can be talked into supporting transferMode, passive and proxyServer (I respond well to itunes gift certificates ;).
Download the attachment.
Can this FTPCFC be combined with Flash's FileReference API for uploading? The Flash FileReference seems to have a 100 megs file limit and I need to find a way around this problem. Any suggestions?
Posted By Jerry / Posted on 11/15/2006 at 12:23 AM
I am not familiar with the Flash FileReference API, so I couldn't tell you. You could integrate this with Flash/Flex, in fact one idea I had was to use it for a Flex-based ftp UI, but remember, since this is FTP you would be moving a file on the local server to a remote FTP location...this is not for uploading files from the client (though I am not sure if that is what you are asking). Nonetheless, 100MB is a rather large limit and would take a long time to upload (if it didn't crap out on you) no matter what method you choose...
Posted By Brian Rinaldi / Posted on 11/15/2006 at 7:19 AM
Brian - nice work, you're always one step ahead ;) I was JUST thinking about doing something like this the other day!! I bet you could make a client tool in flex by combining this with some of the file upload utilities out there. That would definitely be unique - and something I think I'd use very often. Could this be combined with sftp?
You should post this up on RIAForge.
Posted By
todd sharp / Posted on 11/15/2006 at 8:25 AM
Does it allow you to execute raw commands and capture the return?
Posted By
Critter / Posted on 02/16/2007 at 4:54 PM
Critter, I am not quite sure what you mean...the component simply wraps pre-existing cfftp functionality.
Posted By Brian Rinaldi / Posted on 02/16/2007 at 5:44 PM
My bad... yeah that doesn't exist in cfftp.. I saw ftp wrapper and got all excited :)
Posted By
Critter / Posted on 02/17/2007 at 2:57 AM
I am attemptin to use this on a cf8 box and I keep ketting an error just trying to run listDir
this error:
The value returned from the listDir function is not of type query.
I am currently just doing this
<cfset ftpService = createObject("component","ftpService").init("
ftp.myserver.com","username","password") />
<cfset ftpService.open() />
<cfset qryContents = ftpService.listDir() />
any thoughts?
Posted By Jay McConathy / Posted on 02/13/2008 at 1:45 PM
Hmm...not sure. I am running it here on CF8 just fine. There is no need to call the open() function (in fact looking at it this probably could be private) as the init() function already opens the connection for you. However, calling that function doesn't seem to change anything on my end.
It could be the connection got lost somehow.
Posted By Brian Rinaldi / Posted on 02/14/2008 at 10:02 AM
I'm having the same problem with CF8.
The code Jay has above throws me an error in getCurrentDir (which gets called from listDir).
The value of ftp return from <cfftp action="getCurrentURL" connection="variables.connection" result="ftp" /> is an empty string which causes a " You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members." error.
Again, the code is just
<cfset ftpService = createObject("component","ftpService").init("
ftp.myserver.com","username","password") />
<cfset ftpService.open() />
<cfset qryContents = ftpService.listDir() />
Any help would be greatly appreciated.
Posted By Julian / Posted on 03/07/2008 at 4:07 AM
As Julian has sad above
this is still giving me an error
I am attempting to use this on a cf8 box and I keep getting an error just trying to run listDir
The value returned from the listDir function is not of type query.
I am currently just doing this
<cfset ftpService = createObject("component","ftpService").init("
ftp.myserver.com","username","password") />
<cfset ftpService.open() />
<cfset qryContents = ftpService.listDir() />
as shown in a couple of posts there are issues here just trying to figure out how to resolve them
Posted By Jay McConathy / Posted on 03/13/2008 at 8:34 AM
Sorry for the delay in responding. I keep trying to replicate the issue but can't seem to do it. I don't see why it would be the ftp variable since it isn't used. In fact, you can just take it out for that method since it isn't necessary. Does that resolve anything?
Posted By Brian Rinaldi / Posted on 03/19/2008 at 4:58 AM
For me the error is thrown in getCurrentDir() function, which is being called from listDir(), as it's the default argument.
Within getCurrentDir() the action getCurrentDir is performed which returns the variable ftp, which for me on CF8 is an empty string.
The error is thrown by the last line :
<cfreturn
ftp.returnValue />
Which gives
"You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members."
as ftp is [empty string].
Thanks again,
Julian
Posted By Julian / Posted on 03/20/2008 at 1:35 AM
Julian, Keeping in mind that this is just a wrapper for straight cfftp calls, I would recommend you try doing the straight calls because I don't think your issue is in the component. If you see the docs (
http://www.cfquickdocs.com/cf8/#cfftp.connfileanddir) it states "The cf
ftp.returnValue variable provides the return value for...getCurrentDir". Thus, if the ftp variable is returning empty string then I suspect there is a different issue going on with the ftp connection.
Posted By Brian Rinaldi / Posted on 03/20/2008 at 6:45 AM
Thanks Brian, I might have to just try doing the straight calls. Just so you know everything works perfectly for me in CF7.
I tried dumping out Variables.connection at the top of the getCurrentDir() function and compared the output from both.
In CF7 it is an object of org.apache.commons.net.
ftp.FTPClient.
In CF8 it is a structure containing stuff like DefaultPort, LocalAddress, RemoteAddress, RemotePort, Status (211), User etc.
Does this sound right?
Posted By Julian / Posted on 03/20/2008 at 7:15 AM
Brian I was able to replicate the errors reported by Jay and Julian on CF 8.0 (no updates or hot fixes applied).
No issues on CF 8.0.1
Posted By Pragnesh Vaghela / Posted on 07/07/2008 at 7:16 PM