241 votes

Java : Quelle est la meilleure façon de SFTP un fichier à partir d'un serveur ?

Quelle est la meilleure façon de récupérer un fichier sur un serveur en utilisant SFTP (par opposition à FTPS) en utilisant Java ? Je vous laisse le soin de définir ce qu'est le meilleur moyen, mais je pense qu'il doit être gratuit :)

210voto

Cheekysoft Points 16532

Une autre option est d'envisager d'examiner le Bibliothèque JSch . JSch semble être la bibliothèque préférée de quelques grands projets open source, dont Eclipse, Ant et Apache Commons HttpClient, entre autres.

Il prend en charge les connexions par utilisateur/passe et par certificat, ainsi que toute une série d'autres fonctionnalités SSH2.

Voici une simple récupération de fichiers à distance via SFTP. La gestion des erreurs est un exercice pour le lecteur :-)

JSch jsch = new JSch();

String knownHostsFilename = "/home/username/.ssh/known_hosts";
jsch.setKnownHosts( knownHostsFilename );

Session session = jsch.getSession( "remote-username", "remote-host" );    
{
  // "interactive" version
  // can selectively update specified known_hosts file 
  // need to implement UserInfo interface
  // MyUserInfo is a swing implementation provided in 
  //  examples/Sftp.java in the JSch dist
  UserInfo ui = new MyUserInfo();
  session.setUserInfo(ui);

  // OR non-interactive version. Relies in host key being in known-hosts file
  session.setPassword( "remote-password" );
}

session.connect();

Channel channel = session.openChannel( "sftp" );
channel.connect();

ChannelSftp sftpChannel = (ChannelSftp) channel;

sftpChannel.get("remote-file", "local-file" );
// OR
InputStream in = sftpChannel.get( "remote-file" );
  // process inputstream as needed

sftpChannel.exit();
session.disconnect();

1 votes

Cheekysoft, j'ai remarqué - en utilisant Jsch - que la suppression de fichiers sur le serveur sftp ne fonctionne pas. Renommer des fichiers ne fonctionne pas non plus. Une idée s'il vous plaît ? Andy

1 votes

Désolé, ce n'est pas quelque chose avec lequel je travaille en ce moment. (Essayez de laisser ce genre de réponses sous forme de commentaires - comme ce message - et non comme une nouvelle réponse à la question initiale).

1 votes

Quel est ce bloc de code après l'attribution de la session ? S'agit-il d'une syntaxe Java sophistiquée que je n'ai jamais vue ? Si c'est le cas, qu'est-ce que cela accomplit en étant écrit de cette manière ?

118voto

Iraklis Points 1476

Voici le code source complet d'un exemple utilisant JSch sans avoir à se soucier de la vérification de la clé ssh.

import com.jcraft.jsch.*;

public class TestJSch {
    public static void main(String args[]) {
        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession("username", "127.0.0.1", 22);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setPassword("password");
            session.connect();

            Channel channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftpChannel = (ChannelSftp) channel;
            sftpChannel.get("remotefile.txt", "localfile.txt");
            sftpChannel.exit();
            session.disconnect();
        } catch (JSchException e) {
            e.printStackTrace();  
        } catch (SftpException e) {
            e.printStackTrace();
        }
    }
}

18 votes

A finally doit être utilisé pour inclure le code de nettoyage du canal, afin de s'assurer qu'il s'exécute toujours.

0 votes

J'obtiens cette exception maintenant : com.jcraft.jsch.JSchException: Session.connect: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 2048 (inclusive)

0 votes

J'ai trouvé que JSCH avait 0 ou 1 dépendance supplémentaire. Vous pouvez ignorer la dépendance JZLIB si vous désactivez la compression. // désactiver la compression session.setConfig("compression.s2c", "none") ; session.setConfig("compression.c2s", "none") ;

47voto

Chris J Points 3923

Voici un exemple utilisant Apache Common VFS :

FileSystemOptions fsOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
FileSystemManager fsManager = VFS.getManager();
String uri = "sftp://user:password@host:port/absolute-path";
FileObject fo = fsManager.resolveFile(uri, fsOptions);

9 votes

Une autre chose intéressante à faire est de définir le délai d'attente, de sorte que si le système distant est hors ligne, vous ne restiez pas bloqué indéfiniment. Vous pouvez faire cela de la même manière que pour la désactivation de la vérification de la clé d'hôte : SftpFileSystemConfigBuilder.getInstance().setTimeout(fsOptions, 5000) ;

0 votes

Comment conseillez-vous de fermer cette connexion lorsque vous utilisez plusieurs clients SFTP en même temps ?

2 votes

Que faire si mon mot de passe contient le symbole @ ?

24voto

Boris Terzic Points 6148

Apache est une abstraction intéressante au-dessus de Jsch. communs-vfs qui offre une API de système de fichiers virtuel qui rend l'accès et l'écriture de fichiers SFTP presque transparents. Cela a bien fonctionné pour nous.

1 votes

Est-il possible d'utiliser des clés pré-partagées en combinaison avec commons-vfs ?

2 votes

Oui, c'est le cas. Si vous avez besoin d'identités non standard, vous pouvez appeler SftpFileSystemConfigBuilder.getInstance().setIdentities(...).

0 votes

Vous pouvez utiliser des clés pré-partagées. Mais ces clés doivent être sans mot de passe. OtrosLogViewer utilise l'autorisation de clé SSH avec VFS mais nécessite de supprimer la phrase de passe de la clé ( code.google.com/p/otroslogviewer/wiki/SftpAuthPubKey )

23voto

David Hayes Points 2709

Voici la solution que j'ai trouvée http://sourceforge.net/projects/sshtools/ (la plupart des traitements des erreurs sont omis pour des raisons de clarté). Ceci est un extrait de mon blog

SshClient ssh = new SshClient();
ssh.connect(host, port);
//Authenticate
PasswordAuthenticationClient passwordAuthenticationClient = new PasswordAuthenticationClient();
passwordAuthenticationClient.setUsername(userName);
passwordAuthenticationClient.setPassword(password);
int result = ssh.authenticate(passwordAuthenticationClient);
if(result != AuthenticationProtocolState.COMPLETE){
     throw new SFTPException("Login to " + host + ":" + port + " " + userName + "/" + password + " failed");
}
//Open the SFTP channel
SftpClient client = ssh.openSftpClient();
//Send the file
client.put(filePath);
//disconnect
client.quit();
ssh.disconnect();

8 votes

Je suis d'accord (tardivement), cela a bien fonctionné pour le site/téléchargement original dont j'avais besoin, mais cela a refusé de fonctionner pour le nouveau. Je suis en train de passer à JSch.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X