Using Ftp with Grails

04 / Apr / 2013 by Puneet Behl 5 comments

In one of my Grails project I need to drop files over ftp server. Using JSch one can easily transfer files over sftp. Just follow the below steps.
1. Add the below dependency to Grails project “grails-app/conf/BuildConfig.groovy” file

[sourcecode language=”groovy”]
dependencies {
compile ‘com.jcraft:jsch:0.1.49’
}
[/sourcecode]

2. Create a class for adding ftp credentials information. e.g. “FtpCredentail”

[sourcecode language=”groovy”]
class FtpCredential {

String server
String username
String password
String remoteBaseDir
Integer port
}
[/sourcecode]

3. Create a service named “FtpService” and add the following code into it

[sourcecode language=”groovy”]
import com.jcraft.jsch.Channel
import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session

class FtpService {
def grailsApplication

static transactional = true

def save(InputStream inputStream, String fileName, FtpCredential ftpCredential) {
connect(ftpCredential) { ChannelSftp sftp ->
sftp.put inputStream, fileName
}
}

def load(String fileName, FtpCredential ftpCredential) {
connect(ftpCredential, { ChannelSftp sftp ->
File outputFile = File.createTempFile(fileName,”)
outputFile?.newOutputStream() << sftp.get(fileName)
outputFile
}, false)
}

def delete(String fileName, FtpCredential ftpCredential) throws Throwable {
connect(ftpCredential) { ChannelSftp sftp ->
sftp.rm fileName
}
}

def makeDir(String directoryName, FtpCredential ftpCredential) {
connect(ftpCredential) { ChannelSftp sftp ->
sftp.mkdir directoryName
}
}

private def connect(FtpCredential ftpCredential, Closure c, boolean disconnectOnFinish = true) {
Session session = null
ChannelSftp sftp = null
try {
JSch jSch = new JSch()
session = jSch.getSession username, ftpCredential?.server, ftpCredential?.port
session.setConfig "StrictHostKeyChecking", "no"
File keyFile = new File("${grailsApplication.config.pathToKeyFile}")
if (ftpCredential?.password) {
session.password = ftpCredential?.password
} else {
jSch.addIdentity(keyFile?.absolutePath)
}
session.connect()
Channel sFtpChannel = session.openChannel "sftp"
sFtpChannel.connect()
sftp = sFtpChannel as ChannelSftp
sftp.cd ftpCredential?.remoteBaseDir
c.call sftp
} catch (Exception ex) {
ex.printStackTrace()
} finally {
if (disconnectOnFinish) {
sftp?.exit()
session?.disconnect()
}
}
}
}
[/sourcecode]
Note: In the above code at line number 44.
[sourcecode language=”groovy”]
File keyFile = new File("${grailsApplication.config.pathToKeyFile}")
[/sourcecode]
The code looks for private key provided by ftp server for password-less log in. One should define the property named “pathToKeyFile” in “grails-app/conf/Config.groovy” with value equals to the path of key file.

Now you are ready to use the newly created FtpService service methods. Such as:

  1. save(inputStream, fileName, ftpCredential) for saving file over ftp.
  2. load(fileName, ftpCredential) for getting file from ftp.
  3. delete(fileName, ftpCredential) for deleting file over ftp.
  4. makeDir(directoryName, ftpCredential) for creating directory over ftp.

Example

For saving file over ftp one can use FtpService save method as shown below
[sourcecode language=”groovy”]
File file = File.createTempFile("temp","txt")
FtpCredential ftpCredential = new FtpCredential(server: <server>, username: <username>, password: <password>, port: <server_port>, remoteBaseDir: <remote_base_directory>)
InputStream inputStream = new BufferedInputStream(new FileInputStream(file))
ftpService.save(inputStream, "fileNameToBeSavedOverFTPServer", ftpCredential)
[/sourcecode]

Please share your feedback and suggestions.


Click here to read more JSch examples »

FOUND THIS USEFUL? SHARE IT

comments (5)

  1. Andy Birchall

    You’re missing ftpCredential?.username on line 43. Also I think you should make clear that JSch will only work over an SSH channel using SFTP.

    Reply
  2. Artem

    I can’t even connect to ftp! Timeout error, while I successfully connect by cuteFTP or through browser

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *