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

dependencies {
        compile 'com.jcraft:jsch:0.1.49'
    }

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

class FtpCredential {

    String server
    String username
    String password
    String remoteBaseDir
    Integer port
}

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

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()
            }
        }
    }
}

Note: In the above code at line number 44.

File keyFile = new File("${grailsApplication.config.pathToKeyFile}")

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

 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)

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
    1. Puneet Behl Post author

      Here is the github url for the demo project “git@github.com:puneetbehl/ftpDemo.git”

      Reply
  2. Artem

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

    Reply

Leave a comment -