Java SFTP

SFTP

SFTP是Secure File Transfer Protocol的缩写,安全文件传送协议。SFTP为SSH的一部份,是一种传输文件到服务器的安全加密的方式。

JSch

JSch是ssh的Java实现,从官网http://www.jcraft.com/jsch/ 下载jar包(jsch-0.1.55.jar),加入项目即可。

使用JSch连接SFTP

使用JSch连接SFTP服务器操作的步骤大致为:

  1. 使用ip、port、username、password等信息连接sftp,获取Session
  2. Session可以设置一系列属性,如超时时间等,通过Session建立链接
  3. Session建立连接后,打开SFTP通道Channel
  4. Channel连接之后便形成可用的ChannelSftp
  5. JSch封装了常用指令,如:sftp.put()、sftp.cd()、sftp.get()、sftp.ls(),可以进行操作
  6. 操作完成后,要关闭通道Channel和Session。

源码

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Vector;

/**
 * SFTP Utils
 *
 */
public class SFTPUtils {
    private static final Logger logger = LoggerFactory.getLogger(SFTPUtils.class);
    private static int TIMEOUT = 60000; // 超时数为一分钟,默认是0,表示没有超时数,单位毫秒

    private ChannelSftp sftp;

    public static SFTPUtils getInstance(String host, int port, String username, String password) {
        SFTPUtils instance = new SFTPUtils(host, port, username, password);
        return instance;
    }

    private SFTPUtils(String host, int port, String username, String password) {
        sftp = connect(host, port, username, password); // 获取连接
    }

    /**
     * 连接sftp服务器,创建一个sftp通道对象,通过这 个对象可以直接发送文件。
     *
     * @param host
     *            主机
     * @param port
     *            端口
     * @param username
     *            用户名
     * @param password
     *            密码
     * @return
     */
    public ChannelSftp connect(String host, int port, String username, String password) {
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();

            Session sshSession = jsch.getSession(username, host, port);
            sshSession.setPassword(password);
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig); // 为Session对象设置properties
            sshSession.setTimeout(TIMEOUT); // 设置timeout时间
            sshSession.connect(); // 通过Session建立链接
            logger.info("SFTP Session connected.");

            Channel channel = sshSession.openChannel("sftp"); // 打开SFTP通道
            channel.connect(); // 建立SFTP通道的连接
            sftp = (ChannelSftp) channel;
            logger.info("Connected to " + host);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return sftp;
    }

    /**
     * 上传文件
     *
     * @param directory
     *            上传的目录
     * @param uploadFile
     *            要上传的文件全路径
     */
    public boolean upload(String targetDirectory, String uploadFile) {
        try {
            Vector dir = sftp.ls(targetDirectory);
            if (dir == null) { // 如果路径不存在,则创建
                sftp.mkdir(targetDirectory);
            }

            sftp.cd(targetDirectory);
            File file = new File(uploadFile);
            FileInputStream fileInputStream = new FileInputStream(file);
            sftp.put(fileInputStream, file.getName());
            fileInputStream.close();
            return true;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param directory
     *            下载目录
     * @param downloadFile
     *            下载文件名
     * @param saveFile
     *            存在本地的文件全路径
     */
    public File downloadToFile(String directory, String downloadFile, String saveFile) {
        try {
            sftp.cd(directory);
            File file = new File(saveFile);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            sftp.get(downloadFile, fileOutputStream);
            fileOutputStream.close();
            return file;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 
     * @param directory
     *            下载目录
     * @param downloadFile
     *            下载文件名
     * @param saveFilePath
     *            存在本地的路径
     * @return
     */
    public File downloadToDirectory(String directory, String downloadFile, String saveFilePath) {
        try {
            sftp.cd(directory);
            File file = new File(saveFilePath + File.separator + downloadFile);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            sftp.get(downloadFile, fileOutputStream);
            fileOutputStream.close();
            return file;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 下载文件
     *
     * @param downloadFilePath
     *            下载的文件完整目录
     * @param saveFile
     *            存在本地的路径
     */
    public File download(String downloadFilePath, String saveFile) {
        try {
            int i = downloadFilePath.lastIndexOf('/');
            if (i == -1)
                return null;
            sftp.cd(downloadFilePath.substring(0, i));
            File file = new File(saveFile);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            sftp.get(downloadFilePath.substring(i + 1), fileOutputStream);
            fileOutputStream.close();
            return file;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 关闭会话和通道
     */
    public void disconnect() {
        try {
            sftp.getSession().disconnect();
        } catch (JSchException e) {
            logger.error(e.getMessage(), e);
        }
        sftp.quit();
        sftp.disconnect();
    }

    /**
     * 列出目录下的文件
     *
     * @param directory
     *            要列出的目录
     * @throws SftpException
     */
    public Vector<LsEntry> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }

    public static void main(String[] args) throws IOException {
        Logger logger = LoggerFactory.getLogger(SFTPUtils.class);

        String host = "zhangzhiqiang.net";
        int port = 22;
        String username = "silent";
        String password = "Citic123!";

        // 服务器端可供操作的目录
        String serverDirectory = "/upload";

        SFTPUtils sf = null;
        try {
            sf = SFTPUtils.getInstance(host, port, username, password);

            sf.upload(serverDirectory, "C:\\Users\\waiti\\Desktop\\b.xls"); // 上传文件
            sf.downloadToFile(serverDirectory, "b.java", "C:\\Users\\waiti\\Desktop\\b3.java");
            sf.downloadToDirectory(serverDirectory, "b.java", "C:\\Users\\waiti\\Desktop");

            Vector<LsEntry> files = sf.listFiles(serverDirectory); // 查看文件列表
            if (files != null) {
                for (LsEntry file : files) {
                    System.out.println(file.getFilename());
                }
            }
        } catch (SftpException e) {
            logger.error("SFTP Error!", e);
        } finally {
            if (sf != null) {
                sf.disconnect();
            }
        }
    }
}
欣赏此文?求鼓励,求支持!您的支持就是支持我更新的最大动力!