一、SFTP使用场景
ftp是大多数网站的文件传输选择工具,但ftp并不是非常安全,并且在centos上搭建的vsftpd也非常的不稳定,偶尔会出现权限问题,例如500、或是账号密码不正确等等。
而SFTP是基于默认的22端口,是ssh内含的协议,只要启动了sshd就可以使用。
建议:更高的效率使用FTP协议,更安全的通信使用SFTP协议。
FTP是一种文件传输协议,一般是为了方便数据共享的。包括一个FTP服务器和多个FTP客户端。FTP客户端通过FTP协议在服务器上下载资源。而SFTP协议是在FTP的基础上对数据进行加密,使得传输的数据相对来说更安全。但是这种安全是以牺牲效率为代价的,也就是说SFTP的传输效率比FTP要低(不过现实使用当中,没有发现多大差别)。个人肤浅的认为就是:
FTP要安装,SFTP不要安装。
SFTP更安全,但更安全带来副作用就是的效率比FTP要低些。
二、SFTP工具类
这个工具类我写的比较粗糙,涉及到获取指定目录下的文件名,文件上传,文件写入,文件内容读取,文件下载,文件删除等.
此工具类有很多改进的地方…
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.nio.file.Files;
import java.util.Objects;
import java.util.Vector;
/**
* Description: SFTP工具类
* Create DateTime: 2022/10/17 17:07
*
* @author zhangchangsheng01@gmail.com
*/
@Slf4j
public class SftpUtil {
private static ChannelSftp sftp = null;
private static Session session = null;
/**
* 连接sftp服务器
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/17 17:08
* @param username 用户名
* @param password 密码
* @param host 主机ip
* @param port 端口号
* @param privateKey 私钥
* @param timeout 超时时间
* @return com.jcraft.jsch.ChannelSftp
*/
public static ChannelSftp sftpConnect(String username,
String password,
String host,
int port,
String privateKey,
int timeout) throws Exception {
JSch jsch = new JSch();
if (StringUtils.isNotBlank(privateKey)) {
// 设置私钥
jsch.addIdentity(privateKey);
}
//用户名,主机,端口号
session = jsch.getSession(username, host, port);
//密码
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
// 设置timeout时间
session.setTimeout(timeout);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
return sftp;
}
/**
* 获取指定目录下的文件
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/17 17:09
* @param directory 目录
* @return java.util.Vector<?>
*/
public static Vector<?> listFiles(String directory) throws SftpException {
if (sftp == null) {
return null;
}
return sftp.ls(directory);
}
/**
* 获取SFTP文件内容
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/17 17:10
* @param fileName 文件名称
* @param ftpPath 文件路径
* @return java.lang.String
*/
public static String getFtpData(String fileName,String ftpPath) throws SftpException, IOException {
try {
if (null == sftp) {
return null;
}
sftp.cd(ftpPath);
} catch (Exception e) {
e.printStackTrace();
}
InputStream in = sftp.get(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
}
/**
* 本地文件上传到SFTP服务器
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/25 18:53
* @param remotePath 远程SFTP文件目录
* @param remoteFileName 远程SFTP文件名称
* @param localPath 本地文件目录
* @param localFileName 本地文件名
*/
public static void uploadFile(String remotePath, String remoteFileName, String localPath, String localFileName) {
FileInputStream in = null;
try {
sftp.cd(remotePath);
File file = new File(localPath, localFileName);
in = new FileInputStream(file);
sftp.put(in, remoteFileName);
} catch (FileNotFoundException | SftpException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 写入文件
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/31 16:58
* @param remotePath SFTP目录
* @param remoteFileName SFTP文件名
* @param in 输入流
*/
public static void writeFile(String remotePath, String remoteFileName, InputStream in) {
try {
sftp.cd(remotePath);
sftp.put(in, remoteFileName);
} catch (SftpException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 文件下载
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/19 10:49
* @param directory 源目录
* @param downloadFile 源文件名
* @param saveDirectory 保存到的目录
* @param saveFile 保存的文件名
*/
public static void download(String directory, String downloadFile, String saveDirectory, String saveFile) {
OutputStream outputStream = null;
try {
if (StringUtils.isNotBlank(directory)) {
sftp.cd(directory);
}
File file = new File(saveDirectory, saveFile);
outputStream = Files.newOutputStream(file.toPath());
sftp.get(downloadFile, outputStream);
} catch (SftpException | IOException e) {
throw new RuntimeException(e);
} finally {
if (Objects.nonNull(outputStream)) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void mkdir(String directory,String fileName,ChannelSftp sftp){
try {
sftp.cd(directory);
sftp.mkdir(fileName);
log.info("文件夹创建成功");
} catch (Exception e) {
log.error("文件夹创建失败", e);
}
}
/**
*
*
* @author zhangchangsheng01@gmail.com
* @date 2022/11/3 16:58
* @param path 待删除文件或文件夹路径
*/
public static void delete(String path){
if (sftp == null) {
return;
}
try {
// 如果时目录,需要先遍历删除目录下的文件再删除目录
if (sftp.stat(path).isDir()) {
sftp.cd(path);
Vector<ChannelSftp.LsEntry> entries = sftp.ls(".");
for (ChannelSftp.LsEntry entry: entries) {
String fileName = entry.getFilename();
if(fileName.equals(".") || fileName.equals("..")){
continue;
}
delete(entry.getFilename());
}
sftp.cd("..");
sftp.rmdir(path);
} else {
// 具体的文件路径,直接删除
sftp.rm(path);
}
log.info("删除成功:{}", path);
} catch (Exception e) {
log.error("删除失败", e);
}
}
/**
* 关闭FTP连接
*
* @author zhangchangsheng01@gmail.com
* @date 2022/10/17 17:10
*/
public static void closeChannel() {
if (sftp != null) {
sftp.disconnect();
}
if (session != null) {
if (session.isConnected()) {
session.disconnect();
}
}
}
}
三、单元测试
@Test
void testConnectSFTP(){
try {
//创建连接
SftpUtil.sftpConnect(username, password, host, port, null,0);
} catch (Exception e) {
e.printStackTrace();
} finally {
SftpUtil.closeChannel();
}
}
@Test
void testUploadFile(){
String localPath = "";
try {
//创建连接
SftpUtil.sftpConnect(username, password, host, port, null,0);
String fileName = "";
SftpUtil.uploadFile(ftpPath, fileName, localPath, fileName);
} catch (Exception e) {
e.printStackTrace();
} finally {
SftpUtil.closeChannel();
}
}
@Test
void testListFile() throws Exception {
SftpUtil.sftpConnect(username, password, host, port, null, 0);
Vector<?> vector = SftpUtil.listFiles("testDir");
Iterator iterator = vector.iterator();
System.out.println("文件列表:");
while (iterator.hasNext()) {
ChannelSftp.LsEntry file = (ChannelSftp.LsEntry) iterator.next();
//文件名称
System.out.println(file.getFilename());
}
SftpUtil.closeChannel();
}
@Test
void testCreateDirectory(){
try {
//创建连接
ChannelSftp channelSftp = SftpUtil.sftpConnect(username, password, host, port, null, 0);
SftpUtil.mkdir(ftpPath, "errorDirectory", channelSftp);
} catch (Exception e) {
e.printStackTrace();
} finally {
SftpUtil.closeChannel();
}
}
@Test
void testDelete(){
String path = new File(ftpPath, "errorDirectory").getPath();
try {
//创建连接
SftpUtil.sftpConnect(username, password, host, port, null, 0);
SftpUtil.delete(path);
} catch (Exception e) {
e.printStackTrace();
} finally {
SftpUtil.closeChannel();
}
}