Estoy tratando de recuperar un archivo de un servidor usando SFTP (a diferencia de FTPS) usando Java. ¿Cómo puedo hacer esto?
Estoy tratando de recuperar un archivo de un servidor usando SFTP (a diferencia de FTPS) usando Java. ¿Cómo puedo hacer esto?
Respuestas:
Otra opción es considerar mirar la biblioteca JSch . JSch parece ser la biblioteca preferida para algunos grandes proyectos de código abierto, incluidos Eclipse, Ant y Apache Commons HttpClient, entre otros.
Admite muy bien los inicios de sesión de usuario / pase y certificados, así como todas las otras características SSH2 deliciosas.
Aquí hay una simple recuperación remota de archivos a través de SFTP. El manejo de errores se deja como un ejercicio para el lector :-)
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();
Aquí está el código fuente completo de un ejemplo usando JSch sin tener que preocuparse por la comprobación de la clave 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();
}
}
}
finally
debe usar un bloque para incluir el código de limpieza del canal, para garantizar que siempre se ejecute.
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)
A continuación se muestra un ejemplo usando 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);
Esta fue la solución que se me ocurrió http://sourceforge.net/projects/sshtools/ (la mayoría de los errores se omiten para mayor claridad). Este es un extracto de mi 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();
Una buena abstracción sobre Jsch es Apache commons-vfs, que ofrece una API de sistema de archivos virtual que hace que el acceso y la escritura de archivos SFTP sean casi transparentes. Funcionó bien para nosotros.
Hay una buena comparación de las 3 bibliotecas Java maduras para SFTP: Commons VFS, SSHJ y JSch
En resumen, SSHJ tiene la API más clara y es la mejor de ellas si no necesita otro soporte de almacenamiento proporcionado por Commons VFS.
Aquí está el ejemplo editado SSHJ de github :
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts(); // or, to skip host verification: ssh.addHostKeyVerifier(new PromiscuousVerifier())
ssh.connect("localhost");
try {
ssh.authPassword("user", "password"); // or ssh.authPublickey(System.getProperty("user.name"))
final SFTPClient sftp = ssh.newSFTPClient();
try {
sftp.get("test_file", "/tmp/test.tmp");
} finally {
sftp.close();
}
} finally {
ssh.disconnect();
}
Biblioteca SFTP de Apache Commons
Archivo de propiedades de Java común para todos los ejemplos
serverAddress = 111.222.333.444
userId = myUserId
contraseña = myPassword
remoteDirectory = productos /
localDirectory = importar /
Subir archivo al servidor remoto usando SFTP
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
public class SendMyFiles {
static Properties props;
public static void main(String[] args) {
SendMyFiles sendMyFiles = new SendMyFiles();
if (args.length < 1)
{
System.err.println("Usage: java " + sendMyFiles.getClass().getName()+
" Properties_file File_To_FTP ");
System.exit(1);
}
String propertiesFile = args[0].trim();
String fileToFTP = args[1].trim();
sendMyFiles.startFTP(propertiesFile, fileToFTP);
}
public boolean startFTP(String propertiesFilename, String fileToFTP){
props = new Properties();
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
props.load(new FileInputStream("properties/" + propertiesFilename));
String serverAddress = props.getProperty("serverAddress").trim();
String userId = props.getProperty("userId").trim();
String password = props.getProperty("password").trim();
String remoteDirectory = props.getProperty("remoteDirectory").trim();
String localDirectory = props.getProperty("localDirectory").trim();
//check if the file exists
String filepath = localDirectory + fileToFTP;
File file = new File(filepath);
if (!file.exists())
throw new RuntimeException("Error. Local file not found");
//Initializes the file manager
manager.init();
//Setup our SFTP configuration
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
//Create the SFTP URI using the host name, userid, password, remote path and file name
String sftpUri = "sftp://" + userId + ":" + password + "@" + serverAddress + "/" +
remoteDirectory + fileToFTP;
// Create local file object
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(sftpUri, opts);
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload successful");
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally {
manager.close();
}
return true;
}
}
Descargue el archivo del servidor remoto utilizando SFTP
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
public class GetMyFiles {
static Properties props;
public static void main(String[] args) {
GetMyFiles getMyFiles = new GetMyFiles();
if (args.length < 1)
{
System.err.println("Usage: java " + getMyFiles.getClass().getName()+
" Properties_filename File_To_Download ");
System.exit(1);
}
String propertiesFilename = args[0].trim();
String fileToDownload = args[1].trim();
getMyFiles.startFTP(propertiesFilename, fileToDownload);
}
public boolean startFTP(String propertiesFilename, String fileToDownload){
props = new Properties();
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
props.load(new FileInputStream("properties/" + propertiesFilename));
String serverAddress = props.getProperty("serverAddress").trim();
String userId = props.getProperty("userId").trim();
String password = props.getProperty("password").trim();
String remoteDirectory = props.getProperty("remoteDirectory").trim();
String localDirectory = props.getProperty("localDirectory").trim();
//Initializes the file manager
manager.init();
//Setup our SFTP configuration
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
//Create the SFTP URI using the host name, userid, password, remote path and file name
String sftpUri = "sftp://" + userId + ":" + password + "@" + serverAddress + "/" +
remoteDirectory + fileToDownload;
// Create local file object
String filepath = localDirectory + fileToDownload;
File file = new File(filepath);
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(sftpUri, opts);
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
System.out.println("File download successful");
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally {
manager.close();
}
return true;
}
}
Eliminar un archivo en el servidor remoto usando SFTP
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
public class DeleteRemoteFile {
static Properties props;
public static void main(String[] args) {
DeleteRemoteFile getMyFiles = new DeleteRemoteFile();
if (args.length < 1)
{
System.err.println("Usage: java " + getMyFiles.getClass().getName()+
" Properties_filename File_To_Delete ");
System.exit(1);
}
String propertiesFilename = args[0].trim();
String fileToDownload = args[1].trim();
getMyFiles.startFTP(propertiesFilename, fileToDownload);
}
public boolean startFTP(String propertiesFilename, String fileToDownload){
props = new Properties();
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
props.load(new FileInputStream("properties/" + propertiesFilename));
String serverAddress = props.getProperty("serverAddress").trim();
String userId = props.getProperty("userId").trim();
String password = props.getProperty("password").trim();
String remoteDirectory = props.getProperty("remoteDirectory").trim();
//Initializes the file manager
manager.init();
//Setup our SFTP configuration
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
//Create the SFTP URI using the host name, userid, password, remote path and file name
String sftpUri = "sftp://" + userId + ":" + password + "@" + serverAddress + "/" +
remoteDirectory + fileToDownload;
//Create remote file object
FileObject remoteFile = manager.resolveFile(sftpUri, opts);
//Check if the file exists
if(remoteFile.exists()){
remoteFile.delete();
System.out.println("File delete successful");
}
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally {
manager.close();
}
return true;
}
}
hierynomus / sshj tiene una implementación completa de SFTP versión 3 (lo que implementa OpenSSH)
Código de ejemplo de SFTPUpload.java
package net.schmizz.sshj.examples;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.SFTPClient;
import net.schmizz.sshj.xfer.FileSystemFile;
import java.io.File;
import java.io.IOException;
/** This example demonstrates uploading of a file over SFTP to the SSH server. */
public class SFTPUpload {
public static void main(String[] args)
throws IOException {
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
ssh.connect("localhost");
try {
ssh.authPublickey(System.getProperty("user.name"));
final String src = System.getProperty("user.home") + File.separator + "test_file";
final SFTPClient sftp = ssh.newSFTPClient();
try {
sftp.put(new FileSystemFile(src), "/tmp");
} finally {
sftp.close();
}
} finally {
ssh.disconnect();
}
}
}
La biblioteca JSch es la biblioteca poderosa que se puede usar para leer archivos del servidor SFTP. A continuación se muestra el código probado para leer el archivo de la ubicación SFTP línea por línea
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession("user", "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;
InputStream stream = sftpChannel.get("/usr/home/testfile.txt");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException io) {
System.out.println("Exception occurred during reading file from SFTP server due to " + io.getMessage());
io.getMessage();
} catch (Exception e) {
System.out.println("Exception occurred during reading file from SFTP server due to " + e.getMessage());
e.getMessage();
}
sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
Por favor, consulte el blog para todo el programa.
Andy, para eliminar el archivo en el sistema remoto, debes usar (channelExec)
JSch y pasar los comandos unix / linux para eliminarlo.
Pruebe edtFTPj / PRO , una biblioteca cliente SFTP madura y robusta que admite agrupaciones de conexiones y operaciones asincrónicas. También es compatible con FTP y FTPS, por lo que todas las bases para la transferencia segura de archivos están cubiertas.
Encontré un ejemplo de trabajo completo para SFTP en Java usando JSCH API http://kodehelp.com/java-program-for-uploading-file-to-sftp-server/
Aunque las respuestas anteriores fueron muy útiles, pasé un día para que funcionen, enfrentando varias excepciones como "canal roto", "clave rsa desconocida" y "paquete corrupto".
A continuación se muestra una clase reutilizable de trabajo para la carga / descarga de archivos SFTP utilizando la biblioteca JSch.
Subir uso:
SFTPFileCopy upload = new SFTPFileCopy(true, /path/to/sourcefile.png", /path/to/destinationfile.png");
Uso de descarga:
SFTPFileCopy download = new SFTPFileCopy(false, "/path/to/sourcefile.png", "/path/to/destinationfile.png");
El código de clase:
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JOptionPane;
import menue.Menue;
public class SFTPFileCopy1 {
public SFTPFileCopy1(boolean upload, String sourcePath, String destPath) throws FileNotFoundException, IOException {
Session session = null;
Channel channel = null;
ChannelSftp sftpChannel = null;
try {
JSch jsch = new JSch();
//jsch.setKnownHosts("/home/user/.putty/sshhostkeys");
session = jsch.getSession("login", "mysite.com", 22);
session.setPassword("password");
UserInfo ui = new MyUserInfo() {
public void showMessage(String message) {
JOptionPane.showMessageDialog(null, message);
}
public boolean promptYesNo(String message) {
Object[] options = {"yes", "no"};
int foo = JOptionPane.showOptionDialog(null,
message,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo == 0;
}
};
session.setUserInfo(ui);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
channel = session.openChannel("sftp");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
sftpChannel = (ChannelSftp) channel;
if (upload) { // File upload.
byte[] bufr = new byte[(int) new File(sourcePath).length()];
FileInputStream fis = new FileInputStream(new File(sourcePath));
fis.read(bufr);
ByteArrayInputStream fileStream = new ByteArrayInputStream(bufr);
sftpChannel.put(fileStream, destPath);
fileStream.close();
} else { // File download.
byte[] buffer = new byte[1024];
BufferedInputStream bis = new BufferedInputStream(sftpChannel.get(sourcePath));
OutputStream os = new FileOutputStream(new File(destPath));
BufferedOutputStream bos = new BufferedOutputStream(os);
int readCount;
while ((readCount = bis.read(buffer)) > 0) {
bos.write(buffer, 0, readCount);
}
bis.close();
bos.close();
}
} catch (Exception e) {
System.out.println(e);
} finally {
if (sftpChannel != null) {
sftpChannel.exit();
}
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive {
public String getPassword() {
return null;
}
public boolean promptYesNo(String str) {
return false;
}
public String getPassphrase() {
return null;
}
public boolean promptPassphrase(String message) {
return false;
}
public boolean promptPassword(String message) {
return false;
}
public void showMessage(String message) {
}
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo) {
return null;
}
}
}
También tiene JFileUpload con complemento SFTP (Java también): http://www.jfileupload.com/products/sftp/index.html
Utilizo esta API SFTP llamada Zehon, es genial, muy fácil de usar con una gran cantidad de código de muestra. Aquí está el sitio http://www.zehon.com
La mejor solución que he encontrado es Paramiko . Hay una versión de Java.