Java中通过sftp协议实现上传下载

avatar
作者
猴君
阅读量:0

在java开发中,遇到需要将linux系统中指定目录下的文件下载到windows本地的需求,下面聊聊通过sftp协议实现上传和下载。

1、SFTP协议

JSch是Java Secure Channel的缩写。JSch是一个SSH2的纯Java实现。它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到你自己的应用程序。
SFTP是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。SFTP 为 SSH的一部份,是一种传输文件到服务器的安全方式。SFTP是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。

2、SFTP核心类

ChannelSftp类是JSch实现SFTP核心类,它包含了所有SFTP的方法,如:

  • put(): 文件上传
  • get(): 文件下载
  • cd(): 进入指定目录
  • ls(): 得到指定目录下的文件列表
  • rename(): 重命名指定文件或目录
  • rm(): 删除指定文件
  • mkdir(): 创建目录
  • rmdir(): 删除目录
    其他参加源码。
    JSch支持三种文件传输模式:
  • OVERWRITE 完全覆盖模式,这是JSch的默认文件传输模式,即如果目标文件已经存在,传输的文件将完全覆盖目标文件,产生新的文件。
  • RESUME 恢复模式,如果文件已经传输一部分,这时由于网络或其他任何原因导致文件传输中断,如果下一次传输相同的文件,则会从上一次中断的地方续传。
  • APPEND 追加模式,如果目标文件已存在,传输的文件将在目标文件后追加。

编写一个工具类,根据ip,用户名及密码得到一个SFTP channel对象,即ChannelSftp的实例对象,在应用程序中就可以使用该对象来调用SFTP的各种操作方法:

public class SFTPChannel {     Session session = null;     Channel channel = null;      private static final Logger LOG = Logger.getLogger(SFTPChannel.class.getName());      public ChannelSftp getChannel(Map<String, String> sftpDetails, int timeout) throws JSchException {          String ftpHost = sftpDetails.get(“host”);         String port = sftpDetails.get("port");         String ftpUserName = sftpDetails.get("username");         String ftpPassword = sftpDetails.get("password");          int ftpPort = 22;         if (port != null && !port.equals("")) {             ftpPort = Integer.valueOf(port);         }          JSch jsch = new JSch(); // 创建JSch对象         session = jsch.getSession(ftpUserName, ftpHost, ftpPort); // 根据用户名,主机ip,端口获取一个Session对象         LOG.debug("Session created.");         if (ftpPassword != null) {             session.setPassword(ftpPassword); // 设置密码         }         Properties config = new Properties();         config.put("StrictHostKeyChecking", "no");         session.setConfig(config); // 为Session对象设置properties         session.setTimeout(timeout); // 设置timeout时间         session.connect(); // 通过Session建立链接         LOG.debug("Session connected.");          LOG.debug("Opening Channel.");         channel = session.openChannel("sftp"); // 打开SFTP通道         channel.connect(); // 建立SFTP通道的连接         LOG.debug("Connected successfully to ftpHost = " + ftpHost + ",as ftpUserName = " + ftpUserName                 + ", returning: " + channel);         return (ChannelSftp) channel;     }      public void closeChannel() throws Exception {         if (channel != null) {             channel.disconnect();         }         if (session != null) {             session.disconnect();         }     } } 

3、实例

import com.jcraft.jsch.*;   import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.InputStream;   public class SFTPDownloadWithRateLimit {       public static void main(String[] args) {         String host = "hostname";         String username = "username";         String password = "password";         String remoteFile = "/path/to/remote/file";         String localFile = "localFile";         int rateLimit = 1024; // 1KB/s           JSch jsch = new JSch();         try {             Session session = jsch.getSession(username, host, 22);             session.setConfig("StrictHostKeyChecking", "no");             session.setPassword(password);             session.connect();               ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");             channelSftp.connect();                          // 设置下载速率限制             channelSftp.setInputStream(new BufferedInputStream(channelSftp.get(remoteFile), rateLimit));                          InputStream inputStream = channelSftp.get(remoteFile);             BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));               byte[] buffer = new byte[1024];             int bytesRead;             while ((bytesRead = inputStream.read(buffer)) != -1) {                 outputStream.write(buffer, 0, bytesRead);             }               inputStream.close();             outputStream.close();             channelSftp.disconnect();             session.disconnect();         } catch (JSchException | SftpException | java.io.IOException e) {             e.printStackTrace();         }     } }  

import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session;  import java.io.FileOutputStream; import java.io.InputStream;  public class SFTPDownloadWithRateLimit {      public static void main(String[] args) {         String host = "sftp.example.com";         String username = "username";         String password = "password";         int port = 22;         String remoteFilePath = "/path/to/remote/file";         String localFilePath = "/path/to/local/file";         int downloadRate = 1024; // 1 KB/s          try {             JSch jsch = new JSch();             Session session = jsch.getSession(username, host, port);             session.setPassword(password);             session.setConfig("StrictHostKeyChecking", "no");             session.connect();              ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");             channelSftp.connect();              InputStream inputStream = channelSftp.get(remoteFilePath);             FileOutputStream outputStream = new FileOutputStream(localFilePath);              byte[] buffer = new byte[1024];             int bytesRead;             long startTime = System.currentTimeMillis();              while ((bytesRead = inputStream.read(buffer)) != -1) {                 outputStream.write(buffer, 0, bytesRead);                 long elapsedTime = System.currentTimeMillis() - startTime;                 long expectedTime = (outputStream.getChannel().size() / downloadRate) * 1000;                 if (elapsedTime < expectedTime) {                     Thread.sleep(expectedTime - elapsedTime);                 }             }              inputStream.close();             outputStream.close();             channelSftp.disconnect();             session.disconnect();              System.out.println("File downloaded successfully.");         } catch (Exception e) {             e.printStackTrace();         }     } } 

上面是根据指定速率进行下载。

4、工具类

import com.jcraft.jsch.*;  import java.io.*;  public class SFTPUtil {      private String host;     private int port;     private String username;     private String password;      public SFTPUtil(String host, int port, String username, String password) {         this.host = host;         this.port = port;         this.username = username;         this.password = password;     }      public void uploadFile(String localFilePath, String remoteFilePath) {         try {             JSch jsch = new JSch();             Session session = jsch.getSession(username, host, port);             session.setConfig("StrictHostKeyChecking", "no");             session.setPassword(password);             session.connect();              ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");             channelSftp.connect();              channelSftp.put(new FileInputStream(localFilePath), remoteFilePath);              channelSftp.disconnect();             session.disconnect();         } catch (JSchException | SftpException | FileNotFoundException e) {             e.printStackTrace();         }     }      public void downloadFile(String remoteFilePath, String localFilePath) {         try {             JSch jsch = new JSch();             Session session = jsch.getSession(username, host, port);             session.setConfig("StrictHostKeyChecking", "no");             session.setPassword(password);             session.connect();              ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");             channelSftp.connect();              channelSftp.get(remoteFilePath, new FileOutputStream(localFilePath));              channelSftp.disconnect();             session.disconnect();         } catch (JSchException | SftpException | FileNotFoundException e) {             e.printStackTrace();         }     }  } 

JSch支持在文件传输时对传输进度的监控。可以实现JSch提供的SftpProgressMonitor接口来完成这个功能。

  • init(): 当文件开始传输时,调用init方法。
  • count(): 当每次传输了一个数据块后,调用count方法,count方法的参数为这一次传输的数据块大小。
  • end(): 当传输结束时,调用end方法。
public class MyProgressMonitor implements SftpProgressMonitor {     private long transfered;      @Override     public boolean count(long count) {         transfered = transfered + count;         System.out.println("Currently transferred total size: " + transfered + " bytes");         return true;     }      @Override     public void end() {         System.out.println("Transferring done.");     }      @Override     public void init(int op, String src, String dest, long max) {         System.out.println("Transferring begin.");     } } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!