Search code examples
javafilesftpjsch

Downloading Multiple Files via SFTP using Java


I am new to java and I am trying to write a script that will pull multiple files from various SFTP sites daily.

I have code below that will pull 1 file from 1 site and it works, however I am struggling to find how to modify my code so that it will download multiple files. So for example all the files in the remote directory, or only certain files containing certain letters

Can you advise me on this please?

code:-

package package1;  

import java.io.BufferedInputStream;  
import java.io.BufferedOutputStream;  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.OutputStream;  
import com.jcraft.jsch.Channel;  
import com.jcraft.jsch.ChannelSftp;  
import com.jcraft.jsch.JSch;  
import com.jcraft.jsch.Session;  



public class SFTPpullsshkeys {  
public SFTPpullsshkeys() {  
                          }

public static void main(String[] args) {  
        String SFTPHOST = "IP";  
        int    SFTPPORT = 22;  
        String SFTPUSER = "Username";  
        String passphrase = "passphrase";  
        String SFTPWORKINGDIR = "remote directory";    
        String prikeyfile = "C:\\Open SSH Key.ppk";


        Session     session     = null;  
        Channel     channel     = null;  
        ChannelSftp channelSftp = null;  

try{  
        JSch jsch = new JSch();  
        jsch.addIdentity(prikeyfile, passphrase);
        session = jsch.getSession(SFTPUSER,SFTPHOST,SFTPPORT);  
        session.setConfig("StrictHostKeyChecking", "no"); 
        session.connect();  
        channel = session.openChannel("sftp");  
        channel.connect();  
        channelSftp = (ChannelSftp)channel;  
        channelSftp.cd(SFTPWORKINGDIR);  
        byte[] buffer = new byte[1024];  
        BufferedInputStream bis = new BufferedInputStream(channelSftp.get("file.csv"));  
        File newFile = new File("C:\\file.csv"); 
        OutputStream os = new FileOutputStream(newFile);  
        BufferedOutputStream bos = new BufferedOutputStream(os);  
        int readCount;  

while
        ( (readCount = bis.read(buffer)) > 0) {  
        System.out.println("Writing files to disk: " );  
        bos.write(buffer, 0, readCount);  
        }  
        bis.close();  
        bos.close();  
        }catch(Exception ex){  
        ex.printStackTrace();  

        }  

    }      

} 

Solution

  • You can get a directory listing and iterate through it:

        try {
                channel.connect();
                logger.info("shell channel connected....");             
            } catch(JSchException e) {
                logger.warning("Could not connect: " + e.toString());
                logStreamForEmail.close();
    
            }
    
            if (!channel.isConnected()) {
    
                // Close the log stream for email.  This causes it to write all output to the Byte Array Output Stream, which we can dump into email Body Texts
                logStreamForEmail.close();
    
                // Send warning email, could not connect
                new SendEmail(warningEmailAddress, "SFTP Warning: Could not connect to host", baosForEmail.toString());
            } else {   
                try {   
                    ChannelSftp c = (ChannelSftp) channel;   
                    c.lcd(localDir);
                    logger.info("lcd " + c.lpwd());
    
                    // Get a listing of the remote directory
                    @SuppressWarnings("unchecked")
                    Vector<ChannelSftp.LsEntry> list = c.ls("."); 
                    logger.info("ls .");
    
                    // iterate through objects in list, identifying specific file names
                    for (ChannelSftp.LsEntry oListItem : list) {
                        // output each item from directory listing for logs
                        logger.info(oListItem.toString()); 
    
                        // If it is a file (not a directory)
                        if (!oListItem.getAttrs().isDir()) {
                            // Grab the remote file ([remote filename], [local path/filename to write file to])
    
                            logger.info("get " + oListItem.getFilename());
                            c.get(oListItem.getFilename(), oListItem.getFilename());  // while testing, disable this or all of your test files will be grabbed
    
                            grabCount++; 
    
                            // Delete remote file
                            //c.rm(oListItem.getFilename());  // Note for SFTP grabs from this remote host, deleting the file is unnecessary, 
                                                              //   as their system automatically moves an item to the 'downloaded' subfolder
                                                              //   after it has been grabbed.  For other target hosts, un comment this line to remove any downloaded files from the inbox.
                        }
                    }
    
                    // Report files grabbed to log
                    if (grabCount == 0) { 
                        logger.info("Found no new files to grab.");
                    } else {
                        logger.info("Retrieved " + grabCount + " new files.");
                    }                           
                } catch(SftpException e) {
                    logger.warning(e.toString());
                } finally {
                    // disconnect session.  If this is not done, the job will hang and leave log files locked
                    session.disconnect();
                    logger.info("Session Closed");
                }
    

    You can replace all 'logger.warning' and 'logger.info' with System.out.println if you are not using a logger.