实现SFTP的两种方式
手动上传
- 下载Cyberduck
- 新建连接
3.选择SFTP协议,输入ip、用户名、密码/密钥
- 连接成功
- 文件下载:右击文件选择另存为[本地目录]
- 文件上传:粘贴本地文件,复制到窗口中,实现传输
Java上传
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;
import org.apache.commons.lang.StringUtils;
import java.io.InputStream;
import java.util.Properties;
/**
* SFTP 工具类
*/
public final class SftpUtils {
/**
* 私有化
*/
private SftpUtils() {}
/**
* create session
*
* @param sftpHost 主机地址
* @param sftpUsername 用户名
* @param sftpPrivateKeyFile 密钥
* @param sftpPassword 密码
* @return session
* @throws JSchException JSchExp
*/
public static Session connect(String sftpHost, String sftpUsername, String sftpPrivateKeyFile,
String sftpPassword) throws JSchException {
JSch jSch = new JSch();
// 密钥非空时,使用密钥验证
if (StringUtils.isNotEmpty(sftpPrivateKeyFile)) {
jSch.addIdentity(sftpPrivateKeyFile); // 密钥路径
}
// SSH默认TCP端口22
Session session = jSch.getSession(sftpUsername, sftpHost);
// 设置密码
if (StringUtils.isNotEmpty(sftpPrivateKeyFile)) {
session.setUserInfo(new SftpUserInfo(sftpPrivateKeyFile));
} else if (StringUtils.isNotEmpty(sftpPassword)) {
session.setPassword(sftpPassword);
}
// 每次远程登录Linux的时候,Linux都要检查一下,当前访问的计算机公钥是不是在~/.ssh/know_hosts中,
// 禁止检查,避免无法连接SSH,虽然这样做尽管会不安全
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(60 * 1000); // 1分钟超时,单位:milliseconds,可修改
session.connect();
return session;
}
/**
* open channel
*
* @param session session
* @return 结果
* @throws JSchException JSchExp
*/
public static ChannelSftp openChannel(Session session) throws JSchException {
Channel channel = session.openChannel("sftp");
channel.connect();
return (ChannelSftp) channel;
}
/**
* channel断开连接
*
* @param channelSftp channelSftp
*/
public static void disconnect(ChannelSftp channelSftp) {
if (null != channelSftp && channelSftp.isConnected()) {
channelSftp.disconnect();
}
}
/**
* session断开连接
*
* @param session session
*/
public static void disconnect(Session session) {
if (null != session && session.isConnected()) {
session.disconnect();
}
}
/**
* 上传
*
* @param channelSftp SFTP链接
* @param src 源文件地址
* @param dst 目标文件地址
* @throws SftpException SftpExp
*/
public static void upload(ChannelSftp channelSftp, InputStream src, String dst) throws SftpException {
channelSftp.put(src, dst);
}
/**
* 下载
*
* @param channelSftp SFTP链接
* @param src 源文件地址
* @param dst 目标文件地址
* @throws SftpException SftpExp
*/
public static void download(ChannelSftp channelSftp, String src, String dst) throws SftpException {
channelSftp.get(src, dst);
}
}
- 上传功能
// 需要上传的文件,源文件
File file = new File("/Users/xxx/xxx.txt");
// 建立SFTP链接
Session session = null;
ChannelSftp channelSftp = null;
try {
String sftpHost = "您的文件服务器IP";
String sftpUsername = "您的文件服务器登陆用户名";
String sftpPrivateKey = "您的SSH密钥";
String sftpPassword = "您的文件服务器登陆密码,此处与SSH密钥二选一";
session = SftpUtils.connect(sftpHost, sftpUsername, sftpPrivateKey, sftpPassword);
channelSftp = SftpUtils.openChannel(session);
// 上传源文件
InputStream is = new FileInputStream(file);
SftpUtils.upload(channelSftp, is, "/root/" + fileName);
} catch (JSchException | SftpException e) {
e.printStackTrace();
} finally {
// 切记关闭channel后要关闭session
SftpUtils.disconnect(channelSftp);
SftpUtils.disconnect(session);
}
- 下载功能
ChannelSftp channelSftp = null;
Session session = null;
try {
String sftpHost = "您的文件服务器IP";
String sftpUsername = "您的文件服务器登陆用户名";
String sftpPrivateKey = "您的SSH密钥";
String sftpPassword = "您的文件服务器登陆密码,此处与SSH密钥二选一";
session = SftpUtils.connect(sftpHost, sftpUsername, sftpPrivateKey, sftpPassword);
channelSftp = SftpUtils.openChannel(session);
SftpUtils.download(channelSftp, "/root/test.txt", "/Users/xxxx/Desktop/file/");
// 重命名文件可以写清文件名
// SftpUtils.download(channelSftp, "/root/test.txt", "/Users/xxxx/Desktop/file/xxx.txt");
} catch (JSchException | SftpException e) {
e.printStackTrace();
} finally {
SftpUtils.disconnect(channelSftp);
SftpUtils.disconnect(session);
}
- 对于工具类中的类SftpUserInfo, 继承了JSch的类UserInfo,这是必须的
import com.jcraft.jsch.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JSch 登陆信息
*/
public class SftpUserInfo implements UserInfo {
/**
* Logger
*/
private static final Logger logger = LoggerFactory.getLogger(SftpUserInfo.class);
/**
* ssh private key passphrase
*/
private String passphrase;
/**
* 构造函数需要传秘钥的路径,是秘钥的文件路径,不是流也不是秘钥内容
*/
public SftpUserInfo (String passphrase) {
this.passphrase = passphrase;
}
@Override
public String getPassphrase() {
return passphrase;
}
@Override
public String getPassword() {
return null;
}
@Override
public boolean promptPassword(String message) {
return false;
}
@Override
public boolean promptPassphrase(String message) {
return true;
}
@Override
public boolean promptYesNo(String message) {
return true;
}
@Override
public void showMessage(String message) {
logger.info ("SSH Message:{}", message);
}
}