如何通过SFTP从服务器检索文件?

我试图从使用Java的SFTP(而不是FTPS)从服务器检索文件。 我该怎么做?

另一种选择是考虑查看JSch库 。 JSch似乎是一些大型开源项目的首选库,包括Eclipse,Ant和Apache Commons HttpClient等等。

它很好地支持用户/通行证和基于证书的登录,以及所有其他很好的SSH2功能。

这是通过SFTP检索一个简单的远程文件。 错误处理作为读者的练习留下:-)

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

这里是使用JSch的示例的完整源代码,而不必担心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(); } } } 

以下是使用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); 

这是我提出的解决方案http://sourceforge.net/projects/sshtools/ (为清楚起见,大多数错误处理被省略)。 这是我的博客摘录

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

Jsch上的一个很好的抽象是Apache commons-vfs ,它提供了一个虚拟文件系统API,使得访问和写入SFTP文件几乎是透明的。 为我们工作得很好。

Apache Commons SFTP库

所有示例的常见java属性文件

serverAddress = 111.222.333.444

用户id = myUserId

密码= MYPASSWORD

remote目录=产品/

localDirectory =进口/

使用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; } } 

使用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; } } 

使用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; } } 

对于SFTP的3个成熟Java库有一个很好的比较: Commons VFS,SSHJ和JSch

综上所述,SSHJ具有最清晰的API,如果你不需要Commons VFS提供的其他存储支持,那么它是最好的。

这里是从github编辑的SSHJ例子:

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

hierynomus / sshj有一个SFTP版本3的完整实现(OpenSSH实现了什么)

来自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(); } } } 

Andy,要删除远程系统上的文件,需要使用JSch的(channelExec) ,并传入unix / linux命令将其删除。

尝试edtFTPj / PRO ,一个成熟,健壮的SFTP客户端库,支持连接池和异步操作。 还支持FTP和FTPS,因此涵盖所有安全文件传输的基础。

我使用JSCH API在java中找到了完整的SFTP工作示例http://kodehelp.com/java-program-for-uploading-file-to-sftp-server/

虽然上面的答案非常有帮助,但我花了一天的时间让它们工作,面对着诸如“断开的通道”,“rsa密钥未知”和“数据包被破坏”等各种例外。

下面是使用JSch库的SFTP FILES UPLOAD / DOWNLOAD的可重用类。

上传用法:

 SFTPFileCopy upload = new SFTPFileCopy(true, /path/to/sourcefile.png", /path/to/destinationfile.png"); 

下载用法:

 SFTPFileCopy download = new SFTPFileCopy(false, "/path/to/sourcefile.png", "/path/to/destinationfile.png"); 

班级代码:

 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; } } } 

你也有JFileUpload SFTP加载项(也是Java): http ://www.jfileupload.com/products/sftp/index.html

我使用这个名为Zehon的SFTP API,它非常好,很容易使用大量的示例代码。 这是网站http://www.zehon.com

我发现最好的解决方案是Paramiko 。 有一个Java版本。

JSch库是可用于从SFTP服务器读取文件的功能强大的库。 以下是从SFTP位置逐行读取文件的测试代码

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

请参阅博客的整个计划。