文章目录
概要
SFTP
(Secure File Transfer Protocol)是一种基于SSH(Secure Shell)协议的安全文件传输协议
,它提供了在安全信道上进行数据传输的能力。相比传统的FTP(File Transfer Protocol),SFTP具有更高的安全性和更多的功能。
FTP SFTP区别
FTP和SFTP之间的一些主要区别:
特征 | FTP | SFTP |
---|---|---|
协议 | 基于传统的FTP协议(File Transfer Protocol) | 基于SSH的安全文件传输协议(Secure File Transfer Protocol) |
安全性 | 不安全,数据传输未加密 | 安全,所有数据均经过SSH加密传输 |
端口 | 默认端口为21 | 默认端口为22 |
认证 | 可以使用用户名和密码进行简单认证 | 通过SSH密钥或用户名密码进行认证 |
加密 | 不支持加密 | 所有数据传输都通过SSH加密保护 |
目录访问控制 | 依赖FTP服务器的权限和文件系统权限 | 依赖SSH服务器的权限和文件系统权限 |
使用场景 | 用于需要简单文件传输,无需考虑安全性的场景 | 用于需要安全文件传输和操作的场景 |
适用性 | 适用于内部网络和不涉及敏感信息的场景 | 适用于需要加密和安全性要求较高的场景 |
封装一个工具类
import com.jcraft.jsch.*;
import java.io.*;
import java.util.Properties;
import java.util.Vector;
public class SftpUtil {
public static final String NO_FILE = "No such file";
public enum UploadStatus {
Create_Directory_Fail,
Create_Directory_Success,
Upload_New_File_Success,
Upload_New_File_Failed,
File_Exits,
Remote_Bigger_Local,
Upload_From_Break_Success,
Upload_From_Break_Failed,
Delete_Remote_Faild;
}
private ChannelSftp sftp = null;
private Session sshSession = null;
private String username;
private String password;
private String host;
private int port;
public SftpUtil(String host, int port, String username, String password) {
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}
/**
* 连接到sftp服务器
*/
public ChannelSftp connect() throws Exception {
JSch jsch = new JSch();
try {
jsch.getSession(username, host, port);
sshSession = jsch.getSession(username, host, port);
sshSession.setPassword(password);
Properties properties = new Properties();
properties.put("StrictHostKeyChecking", "no");
sshSession.setConfig(properties);
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp)channel;
} catch (JSchException e) {
throw new Exception("FtpUtil-->connect异常" + e.getMessage());
}
return sftp;
}
/**
* 关闭连接
*/
public void disconnect() {
if (this.sftp != null) {
if (this.sftp.isConnected()) {
this.sftp.disconnect();
this.sftp = null;
}
}
if (this.sshSession != null) {
if (this.sshSession.isConnected()) {
this.sshSession.disconnect();
this.sshSession = null;
}
}
}
/**
* 上传文件
* 用于将本地文件上传到指定的远程目录,并且使用给定的文件名。适用于将现有的本地文件上传到SFTP服务器的情况。
*
* @param directory 远程上传目录
* @param uploadFilePath 本地文件路径
* @param fileName 远程文件名
* @throws Exception 可能抛出的异常
*/
public void uploadFile(String directory, String uploadFilePath, String fileName) throws Exception {
FileInputStream in = null;
connect();
try {
sftp.cd(directory);
} catch (SftpException e) {
try {
sftp.mkdir(directory);
sftp.cd(directory);
} catch (SftpException e1) {
throw new Exception("ftp创建文件路径失败,路径为" + directory);
}
}
File file = new File(uploadFilePath);
try {
in = new FileInputStream(file);
sftp.put(in, fileName);
} catch (FileNotFoundException e) {
throw new Exception("文件不存在-->" + uploadFilePath);
} catch (SftpException e) {
throw new Exception("sftp异常-->" + e.getMessage());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
throw new Exception("Close stream error." + e.getMessage());
}
}
disconnect();
}
}
/**
* 上传文件
* 将文件从一个输入流上传到指定的远程路径和文件名。适用于需要从内存中的输入流直接上传文件的情况。
*
* @param filePath 远程文件路径
* @param filename 文件名
* @param in 输入流
* @return 上传状态
*/
public UploadStatus uploadFile(String filePath, String filename, InputStream in) {
try {
sftp.put(in, filePath + filename, ChannelSftp.OVERWRITE);
} catch (SftpException e) {
e.printStackTrace();
}
return UploadStatus.Upload_From_Break_Success;
}
/**
* 获取文件列表
*
* @param filePath 远程文件路径
* @return 文件列表
*/
public Vector<LsEntry> getFileList(String filePath) {
Vector<LsEntry> list = new Vector<>();
try {
Vector veItem = sftp.ls(filePath);
for (Object obj : veItem) {
if (obj instanceof LsEntry) {
list.add((LsEntry)obj);
}
}
} catch (SftpException e) {
e.printStackTrace();
}
return list;
}
/**
* 下载文件
*
* @param directory 远程下载目录
* @param remoteFileName 远程文件名
* @param localFile 本地文件路径
* @return 下载的文件对象
* @throws Exception 可能抛出的异常
*/
public File downloadFile(String directory, String remoteFileName, String localFile) throws Exception {
connect();
File file = null;
OutputStream output = null;
try {
file = new File(localFile);
if (file.exists()) {
file.delete();
}
file.createNewFile();
sftp.cd(directory);
output = new FileOutputStream(file);
sftp.get(remoteFileName, output);
} catch (SftpException e) {
if (e.toString().equals(NO_FILE)) {
throw new Exception("FtpUtil-->downloadFile--ftp下载文件失败" + directory + remoteFileName + "不存在");
}
throw new Exception("ftp目录或者文件异常,检查ftp目录和文件" + e.toString());
} catch (FileNotFoundException e) {
throw new Exception("本地目录异常,请检查" + file.getPath() + e.getMessage());
} catch (IOException e) {
throw new Exception("创建本地文件失败" + file.getPath() + e.getMessage());
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
throw new Exception("Close stream error." + e.getMessage());
}
}
disconnect();
}
return file;
}
}
解释代码:
connect()
函数:
- 创建
JSch
对象。 - 通过
getSession
方法获取会话,并设置用户名、主机、端口和密码。 - 创建属性对象,并将
StrictHostKeyChecking
设置为no
,然后应用到会话配置中。 - 连接会话。
- 打开
sftp
通道并进行连接。 - 将通道强转为
ChannelSftp
类型并赋值给sftp
。 - 最后返回
sftp
对象。
disconnect()
函数:
- 检查
sftp
对象是否不为空且已连接,如果是,则断开连接并将其置为null
。 - 检查
sshSession
对象是否不为空且已连接,如果是,则断开连接并将其置为null
。
public void uploadFile(String directory, String uploadFilePath, String fileName) throws Exception {}
方法:
- 调用
connect
方法建立连接。 - 尝试切换到指定的目录,如果目录不存在则创建目录后再切换。
- 读取要上传的文件,并通过
sftp.put
方法将文件上传。 - 处理可能出现的文件未找到、
SFTP
异常等情况。 - 在
finally
块中,若文件输入流不为空则关闭,并调用disconnect
方法断开连接。
downloadFile
函数:
- 调用
connect
方法建立连接。 - 创建本地文件,如果文件已存在则先删除再创建新文件。
- 切换到指定目录。
- 创建文件输出流。
- 通过
sftp.get
方法从远程获取文件并写入本地输出流。 - 处理可能出现的
SFTP
异常、文件未找到异常、本地目录异常、创建本地文件异常等情况。 - 在
finally
块中,若输出流不为空则关闭,并调用disconnect
方法断开连接。 - 最后返回下载的本地文件。
❤觉得有用的可以留个关注~❤