欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SFTP Java协议应用

程序员文章站 2022-04-15 19:31:22
  · FTP服务器搭建  本文使用Win10搭建的SFTP服务器,关于Win10下SFTP服务器的搭建,搭建可以参考本博的另一篇博文《Win10 基于FreeSSHd搭建SFTP服务 配置详解》。  · Maven 依赖 com.jcraft jsch 0.1.55

  · FTP服务器搭建

  本文使用Win10搭建的SFTP服务器,关于Win10下SFTP服务器的搭建,搭建可以参考本博的另一篇博文《Win10 基于FreeSSHd搭建SFTP服务 配置详解》

  · Maven 依赖

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

  · SFTP 工具类

package com.arhorchin.securitit.protocol.sftp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

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

/**
 * @author Securitit.
 * @note SFTP协议连接共享文件夹.
 */
public class SftpUtil {

    /**
     * logger.
     */
    private Logger logger = Logger.getLogger(SftpUtil.class);

    /**
     * sftp.
     */
    private ChannelSftp sftp;

    /**
     * session.
     */
    private Session session;

    /**
     * SFTP 登录用户名.
     */
    private String username;

    /**
     * SFTP 登录密码.
     */
    private String pp;

    /**
     * 私钥.
     */
    private String privateKey;

    /**
     * SFTP 服务器地址IP地址.
     */
    private String host;

    /**
     * SFTP 端口.
     */
    private int port;

    /**
     * 构造基于密码认证的sftp对象.
     * @param username .
     * @param pp .
     * @param host .
     * @param port .
     */
    public SftpUtil(String username, String pp, String host, int port) {
        this.username = username;
        this.pp = pp;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象.
     * @param username .
     * @param host .
     * @param port .
     * @param privateKey .
     */
    public SftpUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    /**
     * 连接sftp服务器.
     */
    public void sftpLogin() throws Exception {
        JSch jsch = null;
        Properties config = null;
        Channel channel = null;

        try {
            JSch.setLogger(new SftpLogger());
            jsch = new JSch();
            // 设置私钥.
            if (privateKey != null) {
                jsch.addIdentity(privateKey);
            }
            session = jsch.getSession(username, host, port);
            // 设置密码.
            if (pp != null) {
                session.setPassword(pp);
            }
            config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("PreferredAuthentications", "password");

            session.setConfig(config);
            session.connect(10000);

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

            sftp = (ChannelSftp) channel;
        } catch (JSchException ex) {
            logger.error(ex);
            throw new Exception(ex);
        }
    }

    /**
     * 关闭连接 server.
     */
    public void sftpLogout() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 上传文件.
     * @param sftpBasepath 基础目录.
     * @param sftpFilename 文件名称.
     * @param fileBytes 文件内容.
     * @throws SftpException .
     * @return 上传结果.
     */
    public boolean sftpUpload(String sftpBasepath, String sftpFilename, byte[] fileBytes) throws Exception {
        ByteArrayInputStream sftpFileBais = null;

        try {
            sftp.cd(sftp.getHome());
            if (!StringUtils.isEmpty(sftpBasepath)) {
                sftpMkdir(sftpBasepath);
            }
            sftpFileBais = new ByteArrayInputStream(fileBytes);
            sftp.put(sftpFileBais, sftpFilename);
            return true;
        } catch (SftpException ex) {
            logger.error(ex);
            return false;
        }
    }

    /**
     * 下载文件.
     * @param sftpBasepath 基础目录.
     * @param sftpFilename 文件名称.
     * @throws SftpException .
     * @throws FileNotFoundException.
     * @return 下载文件.
     */
    public byte[] download(String sftpBasepath, String sftpFilename) throws Exception {
        ByteArrayOutputStream sftpFileBaos = null;

        try {
            sftp.cd(sftp.getHome());
            if (!StringUtils.isEmpty(sftpBasepath)) {
                sftpMkdir(sftpBasepath);
            }
            sftpFileBaos = new ByteArrayOutputStream();
            sftp.get(sftpFilename, sftpFileBaos);
            return sftpFileBaos.toByteArray();
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        }
    }

    /**
     * 删除文件.
     * @param sftpBasepath 基础目录.
     * @param sftpFilename 文件名称.
     * @throws SftpException.
     * @return 删除结果.
     */
    public boolean delete(String sftpBasepath, String sftpFilename) throws Exception {
        try {
            sftp.cd(sftp.getHome());
            if (!StringUtils.isEmpty(sftpBasepath)) {
                sftpMkdir(sftpBasepath);
            }
            sftp.rm(sftpFilename);
            return true;
        } catch (Exception ex) {
            logger.error(ex);
            return false;
        }
    }

    /**
     * 列出目录下的文件.
     * @param sftpDirectory 目录.
     * @return 目录内容.
     * @throws SftpException .
     */
    public Vector<?> sftpListFiles(String sftpDirectory) throws Exception {
        return sftp.ls(sftpDirectory);
    }

    /**
     * 创建多层目录.
     * @param sftpPath .
     * @throws Exception .
     */
    public void sftpMkdir(String sftpPath) throws Exception {
        try {
            sftp.cd(sftpPath);
        } catch (SftpException e) {
            String[] dirs = sftpPath.split("/");
            String tempPath = sftp.getHome();
            for (String dir : dirs) {
                if (null == dir || "".equals(dir))
                    continue;
                tempPath += "/" + dir;
                try {
                    sftp.cd(tempPath);
                } catch (SftpException ex) {
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }
    }

}

  · 测试类如下:

package com.arhorchin.securitit.protocol.sftp;

import java.io.File;

import org.apache.commons.io.FileUtils;

/**
 * @author Securitit.
 * @note SftpUtil测试.
 */
public class SftpUtilTester {

    public static void main(String[] args) throws Exception {
        String sftpIp = "192.168.120.1";
        Integer sftpPort = 22;
        String sftpUsername = "sftp";
        String sftpPassword = "123456";

        SftpUtil sftp = null;
        // 登录SFTP服务器.
        sftp = new SftpUtil(sftpUsername, sftpPassword, sftpIp, sftpPort);
        sftp.sftpLogin();
        // 上传文件.
        byte[] fileBytes = FileUtils.readFileToByteArray(new File("C:/Users/Administrator/Downloads/个人文件/test.pdf"));
        sftp.sftpUpload("/Test", "test.pdf", fileBytes);
        // 下载文件.
        fileBytes = sftp.sftpDownload("/Test", "test.pdf");
        System.out.println("下载文件大小:" + fileBytes.length);
        // 删除文件.
        sftp.sftpDelete("/Test", "test.pdf");
        // 退出SFTP登录.
        sftp.sftpLogout();
    }

}

  · 总结

  · 监控服务器SFTP物理路径可以看到文件的变化。

  · 测试类输出内容中,可以看到下载的文件长度,说明下载成功了。

  · SftpUtil工具类可以拿来直接使用,本人已进行过简单测试。

  · com.jcraft.jsch.JSchException: Auth fail 如果发生Auth fail,则需要检查自己的配置,按照如下配置检查:

    ① 首先确认FreeSSHd以管理员方式启动

    ② 对FreeSSHd用户进行重新设置:重新启动FreeSSHd进程,使用删除+新增操作代替修改用户操作,删除用户,然后新增用户并设置认证方式和权限等信息,最后启动服务。

本文地址:https://blog.csdn.net/securitit/article/details/107590372