rage
rage

Reputation: 1837

How to tell if an SFTP upload was successful using JSch

Unfortunately the getExitStatus() method always returns -1 so i can't use that to tell me whether or not a file upload worked. I tried to use the getInputStream() method of the Channel class but whenever i tried to read from the inputstream my code blocked forever as if the Channel instance was still open/connected (even though the isConnected and isClosed() were false and true respectively - suggesting that the Channel was indeed closed). The following code always blocks after i try to read a byte of data from the input stream:

public class Put {

public static void main(String[] args) throws IOException {

    Session session = null; 
    Channel channel = null; 
    ChannelSftp channelSftp = null; 
    InputStream in = null; 
    JSch jsch = new JSch();

    try {
        jsch.setKnownHosts("known_hosts");
        session = jsch.getSession("user", "host", 22);
        session.setPassword("password");

        session.connect();
        channel = session.openChannel("sftp");
        channel.setInputStream(null);
        stdout = channel.getInputStream();

        channel.connect();
        channelSftp = (ChannelSftp)channel;
        channelSftp.cd("/path/to/sftp");


        channelSftp.put("/path/to/localfile", "/path/to/remotefile");

    } catch (JSchException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    } catch (SftpException e) {
        System.out.println(e.id);
        System.out.println(e.getMessage());
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {

        if(channelSftp != null && channelSftp.isConnected())channelSftp.exit();
        if(channel != null && channel.isConnected()) channel.disconnect();
        if(session != null && session.isConnected()) session.disconnect();
    }

    System.out.println("Channel is connected? " + channel.isConnected()); // returns false as i would expect
    System.out.println("Channel is closed? " + channel.isClosed()); // returns true as i would expect
    System.out.println(stdout.available()); // returns 0
    System.out.println(stdout.read()); // code blocks here

}

}

I suppose my questions are:

  1. Why is my code blocking whenever i try to read from the input stream (even though the Channel is indeed closed)

  2. What is the way to tell if a file upload worked or not. I guess if a SFTPException is thrown that's unsuccessful otherwise i can assume it was successful?

Upvotes: 6

Views: 9403

Answers (2)

Akhil Appini
Akhil Appini

Reputation: 1

How to Check if a File Exists on an SFTP Server Using JSch in Java?

If you're working with JSch to interact with an SFTP server in Java, you might need to verify whether a file exists before performing operations like reading, downloading, or deleting it. The stat() method of ChannelSftp can be used for this purpose.

Implementation: The following method attempts to retrieve the file attributes using channelSftp.stat(remoteFilePath). If the file exists, the method returns true. If the file does not exist, it catches the SftpException and checks if the error code is SSH_FX_NO_SUCH_FILE, indicating that the file is missing.

private boolean verifyFileExists(ChannelSftp channelSftp, String remoteFilePath) {
    try {
        // Attempt to get the file attributes
        channelSftp.stat(remoteFilePath);
        System.out.println("File exists on the remote server: " + remoteFilePath);
        return true;
    } catch (SftpException e) {
        if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
             System.out.println("File does not exist on the remote server: " + remoteFilePath);
        } else {
            System.out.println("Error checking file existence: " + e.getMessage());
        }
        return false;
    }
}

Explanation:

  1. The method tries to retrieve the file metadata using stat(remoteFilePath).

  2. If the file exists, stat() executes successfully, and we return true.

  3. If an SftpException occurs:

    i)If an SftpException occurs: If the error code is SSH_FX_NO_SUCH_FILE, the file does not exist, and we return false.

    ii)For any other exception, an error message is printed, and false is returned.

Why Use stat() Instead of ls()?

While ls() can list files, it is inefficient for checking a single file's existence because it retrieves a list of files and requires additional processing. Using stat() is more efficient for this specific use case.

Upvotes: 0

Kenster
Kenster

Reputation: 25380

I guess if a SFTPException is thrown that's unsuccessful otherwise i can assume it was successful?

That is correct. The various ChannelSftp.put() functions will throw an exception if they fail for any reason. If you want to double-check, you could call ChannelSftp.stat() or ...lstat() on the remote filename afterwards to check it. But be aware that another process could hypothetically delete or move the remote file before you got a chance to check it.

You don't normally need to access the input or output streams of a ChannelSftp. getExitStatus() would tell you the exit status of the SFTP session as a whole, rather than the result of a particular operation.

JCraft has an example program illustrating how to do SFTP that you might find useful.

Upvotes: 8

Related Questions