【烦人的SFTP传输】Java通过SFTP传输文件

开箱即用,直接上代码

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.8.0</version>
</dependency>

<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.55</version>
</dependency>
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;

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

/**
 * Sftp工具类
 *
 * @author hcf
 * @date 2021/6/26 16:38
 */
@Slf4j
public class SftpUtils {

    private static final String NO_LOGIN = "0";

    /**
     * 向SFTP服务器上传文件
     *
     * @param host       SFTP服务器ip
     * @param port       SFTP服务器端口
     * @param username   SFTP登录账号
     * @param password   SFTP登录密码
     * @param privateKey 免密私钥路径
     * @param loginType  登录方式
     * @param filePath   远程存放路径
     * @param filename   文件名
     * @param is         输入流
     * @return 成功返回true,否则返回false
     */
    public static boolean uploadFileSftp(String host, int port, String username, String password, String privateKey,
                                         String loginType, String filePath, String filename, InputStream is) {
        JSch jsch = new JSch();
        try {
            // 获取sshSession  账号-ip-端口
            Session sshSession = jsch.getSession(username, host, port);
            if (StringUtils.isNotBlank(privateKey) && StringUtils.equals(NO_LOGIN, loginType)) {
                jsch.addIdentity(privateKey);
            } else {
                sshSession.setPassword(password);
            }
            return uploadFileSftp(sshSession, filePath, filename, is);
        } catch (Exception e) {
            log.error("SFTP服务器 文件上传失败 失败原因:{}", e.getMessage(), e);
            return false;
        }
    }

    private static boolean uploadFileSftp(Session sshSession, String filePath,
                                          String filename, InputStream is) throws Exception {
        boolean success = true;
        FTPClient ftp = new FTPClient();
        try {
            ChannelSftp sftp = connectServer(sshSession, ftp, filePath);
            sftp.put(is, filename);
            is.close();
            sftp.quit();
        } catch (Exception e) {
            log.error(" SFTP服务器 文件上传失败 失败原因:{}", e.getMessage(), e);
            throw new Exception(" SFTP服务器文件上传失败,失败原因:" + e.getMessage());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    log.error("SFTP服务器 关闭失败 失败原因:{}", e.getMessage(), e);
                    success = false;
                }
            }
            if (sshSession.isConnected()) {
                sshSession.disconnect();
            }
        }
        return success;
    }

    private static ChannelSftp connectServer(Session sshSession, FTPClient ftp, String filePath) throws Exception {
        Properties sshConfig = new Properties();
        // 严格主机密钥检查
        sshConfig.put("StrictHostKeyChecking", "no");
        sshSession.setConfig(sshConfig);
        // 开启sshSession链接
        sshSession.connect();
        // 获取sftp通道
        Channel channel = sshSession.openChannel("sftp");
        // 开启
        channel.connect();
        ChannelSftp sftp = (ChannelSftp) channel;
        // 设置为被动模式
        ftp.enterLocalPassiveMode();
        sftp.cd(filePath);
        return sftp;
    }


    /**
     * 向SFTP服务器上传大文件
     *
     * @param host       SFTP服务器ip
     * @param port       SFTP服务器端口
     * @param username   SFTP登录账号
     * @param password   SFTP登录密码
     * @param filePath   远程存放路径
     * @param filename   文件名
     * @param clientFile 本地文件
     * @return 成功返回true,否则返回false
     */
    public static boolean uploadBigFileSftp(String host, int port, String username, String password, String privateKey,
                                            String loginType, String filePath, String filename, String clientFile) {
        JSch jsch = new JSch();
        try {
            // 获取sshSession  账号-ip-端口
            Session sshSession = jsch.getSession(username, host, port);
            if (StringUtils.isNotBlank(privateKey) && StringUtils.equals(NO_LOGIN, loginType)) {
                jsch.addIdentity(privateKey);
            } else {
                sshSession.setPassword(password);
            }
            return uploadBigFileSftp(sshSession, filePath, filename, clientFile);
        } catch (Exception e) {
            log.error("SFTP服务器 文件上传失败 失败原因:{}", e.getMessage(), e);
            return false;
        }
    }

    private static boolean uploadBigFileSftp(Session sshSession, String filePath,
                                             String filename, String clientFile) throws Exception {
        boolean success = true;
        FTPClient ftp = new FTPClient();
        try {
            ChannelSftp sftp = connectServer(sshSession, ftp, filePath);
            sftp.put(new FileInputStream(clientFile), filename);
            sftp.quit();
        } catch (Exception e) {
            log.error("SFTP服务器上传文件 {} 失败 失败原因:{}", clientFile, e.getMessage(), e);
            throw new Exception("SFTP服务器上传文件 " + clientFile + " 失败 失败原因:" + e.getMessage());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    log.error("SFTP服务器 关闭失败 失败原因:{}", e.getMessage(), e);
                    success = false;
                }
            }
            if (sshSession.isConnected()) {
                sshSession.disconnect();
            }
        }
        return success;
    }

    /**
     * 从 SFTP 服务器下载文件
     *
     * @param host           SFTP服务器ip
     * @param port           SFTP服务器端口
     * @param username       SFTP登录账号
     * @param password       SFTP登录密码
     * @param privateKey     密钥路径
     * @param loginType      登录方式
     * @param filePath       文件路径
     * @param filename       文件名
     * @param clientFilePath 下载路径
     * @return 本地路径
     */
    public static String downLoadFileSftp(String host, int port, String username, String password, String privateKey,
                                          String loginType, String filePath, String filename, String clientFilePath) {
        FTPClient ftp = new FTPClient();
        JSch jsch = new JSch();
        try {
            File file = new File(clientFilePath);
            if (!file.exists()) {
                file.mkdirs();
            }
            // 获取sshSession  账号-ip-端口
            Session sshSession = jsch.getSession(username, host, port);
            if (StringUtils.isNotBlank(privateKey) && StringUtils.equals(NO_LOGIN, loginType)) {
                sshSession.setPassword(privateKey);
            } else {
                sshSession.setPassword(password);
            }
            ChannelSftp sftp = connectServer(sshSession, ftp, filePath);
            FileOutputStream fos = new FileOutputStream(clientFilePath + File.separator + filename);
            sftp.get(filename, fos);
            fos.close();
            return clientFilePath;
        } catch (Exception e) {
            log.error("SFTP服务器 文件上传失败 失败原因:{}", e.getMessage(), e);
            return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    log.error("SFTP服务器 关闭失败 失败原因:{}", e.getMessage(), e);
                }
            }
        }
    }
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值