目录
- 前言
- 一、什么是SFTP?
- 二、使用工具FileZilla
- (一)配置
- (二)使用
- 三、代码部分
- 总结
前言
最近由于安全监管部门的要求,将系统生成的接口文件存储地址NAS模式更换为符合要求的SFTP模式。所以学习了一下Java如何集成SFTP,然后总结下使用经验。
请等米下锅的同学,请直接转到代码部分
一、什么是SFTP?
安全文件传输协议SFTP(SSH File Transfer Protocol)是文件传输协议(FTP)的安全版本,也是SSH协议的一部分,可通过安全SHELL(SSH)数据流轻松进行数据传输和数据访问。SFTP也被称为SSH文件传输协议。它提供了一个安全的连接来传输文件,并在本地和远程系统上遍历文件系统。SFTP中的加密是通过SSH连接来完成的,文件可以通过WinSCP和SFTP客户端进行传输。
详细参考:什么是SFTP?简述SFTP的工作原理和优势
二、使用工具FileZilla
(一)配置
1、点击文件
,选择站点管理器
。
2、选择SFTP
安全文件传输协议,配置host地址
,账户
,密码
,端口号
不加默认就是22。
3、点击连接
,进入服务器。
(二)使用
点击右键就可以下载、删除了。遇到没有权限的文件,记得给文件赋予权限,或者换到权限更大的root权限。
三、代码部分
ok!进入我们今天的重点部分。我们可以使用插件jcraft
来实现java通过SFTP实现对文件的操作。以下是Springboot
项目的集成,其他框架的项目亦可。
- maven依赖,配置
pom.xml
<!-- sftp上传依赖包 -->
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
大家也可以去maven仓库选择不同的版本下载,像我这里就是选择的最新的依赖包。
https://mvnrepository.com/artifact/com.jcraft/jsch
- 创建配置类
SFTPConfigModel
/**
* 构造SFTP连接的配置类
* @Author:QY
*/
public class SFTPConfigModel {
/** FTP 登录用户名*/
private String userName;
/** FTP 登录密码*/
private String passWord;
/** 私钥 */
private String privateKey;
/** FTP 服务器地址IP地址*/
private String host;
/** FTP 端口*/
private int port;
/** FTP 指定上传路径*/
private String uploadUrl;
/** FTP 指定下载路径*/
private String downloadUrl;
public SFTPConfigModel(String userName, String passWord, String privateKey, String host, int port, String uploadUrl, String downloadUrl) {
this.userName = userName;
this.passWord = passWord;
this.privateKey = privateKey;
this.host = host;
this.port = port;
this.uploadUrl = uploadUrl;
this.downloadUrl = downloadUrl;
}
public SFTPConfigModel(String userName, String passWord, String privateKey, String host, int port) {
this.userName = userName;
this.passWord = passWord;
this.privateKey = privateKey;
this.host = host;
this.port = port;
}
public SFTPConfigModel(String userName, String passWord, String host, int port) {
this.userName = userName;
this.passWord = passWord;
this.host = host;
this.port = port;
}
public SFTPConfigModel(){}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUploadUrl() {
return uploadUrl;
}
public void setUploadUrl(String uploadUrl) {
this.uploadUrl = uploadUrl;
}
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
// -------------------------------------------------------------------------------
public SFTPConfigModel userName(String userName){
this.userName = userName;
return this;
}
public SFTPConfigModel passWord(String passWord){
this.passWord = passWord;
return this;
}
public SFTPConfigModel privateKey(String privateKey){
this.privateKey = privateKey;
return this;
}
public SFTPConfigModel host(String host){
this.host = host;
return this;
}
public SFTPConfigModel port(int port){
this.port = port;
return this;
}
/**
* 默认配置,本人写着测试的。大家需要自己配
* @return
*/
public SFTPConfigModel getDefaultConfig(){
this.userName = "username";
this.passWord = "password";
this.host = "0.0.0.0";
this.port = 22;
this.uploadUrl = "/home/";
return this;
}
@Override
public String toString() {
return "SFTPConfigModel{" +
"userName='" + userName + '\'' +
", passWord='" + passWord + '\'' +
", privateKey='" + privateKey + '\'' +
", host='" + host + '\'' +
", port=" + port +
", uploadUrl='" + uploadUrl + '\'' +
", downloadUrl='" + downloadUrl + '\'' +
'}';
}
}
- 连接工具类
SFTPUtil
import com.jcraft.jsch.*;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Properties;
import java.util.Vector;
/**
* @Author:QY
* @ClassName: SFTPUtil
* @Description: sftp连接工具类
* @date 2020-12-03
* @version 1.0.0
*/
public class SFTPUtil {
private final Logger log = LoggerFactory.getLogger(SFTPUtil.class);
private ChannelSftp sftp;
private Session session;
/** FTP 登录用户名*/
private String username;
/** FTP 登录密码*/
private String password;
/** 私钥 */
private String privateKey;
/** FTP 服务器地址IP地址*/
private String host;
/** FTP 端口*/
private int port;
private SFTPUtil(){}
/**
* QY
* 建议使用配置构参方式,可拓展性比较强
* @param sftpConfigModel
*/
public SFTPUtil(SFTPConfigModel sftpConfigModel){
this.username = sftpConfigModel.getUserName();
this.password = sftpConfigModel.getPassWord();
this.privateKey = sftpConfigModel.getPrivateKey();
this.host = sftpConfigModel.getHost();
this.port = sftpConfigModel.getPort();
}
/**
* 连接sftp服务器
*
* @throws Exception
*/
public void login(){
try {
JSch jsch = new JSch();
if (privateKey != null) {
jsch.addIdentity(privateKey);// 设置私钥
log.info("sftp connect,path of private key file:{}" , privateKey);
}
log.info("sftp connect by host:{} username:{}",host,username);
session = jsch.getSession(username, host, port);
log.info("Session is build");
if (password != null) {
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
log.info("Session is connected");
Channel channel = session.openChannel("sftp");
channel.connect();
log.info("channel is connected");
sftp = (ChannelSftp) channel;
log.info(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
} catch (JSchException e) {
log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
}
}
/**
* 关闭连接 server
*/
public void logout(){
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
log.info("sftp is closed already");
}
}
if (session != null) {
if (session.isConnected()) {
session.disconnect();
log.info("sshSession is closed already");
}
}
}
/**
* 将输入流的数据上传到sftp作为文件
*
* @param directory
* 上传到该目录
* @param sftpFileName
* sftp端文件名
* @param input
* 输入流
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, InputStream input) throws SftpException{
try {
sftp.cd(directory);
} catch (SftpException e) {
log.warn("directory is not exist");
sftp.mkdir(directory);
sftp.cd(directory);
}
sftp.put(input, sftpFileName);
log.info("file:{} is upload successful" , sftpFileName);
}
/**
* 上传单个文件
*
* @param directory
* 上传到sftp目录
* @param uploadFile
* 要上传的文件,包括路径
* @throws FileNotFoundException
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String uploadFile) throws FileNotFoundException, SftpException{
File file = new File(uploadFile);
upload(directory, file.getName(), new FileInputStream(file));
}
/**
* 将byte[]上传到sftp,作为文件。注意:从String生成byte[]是,要指定字符集。
*
* @param directory
* 上传到sftp目录
* @param sftpFileName
* 文件在sftp端的命名
* @param byteArr
* 要上传的字节数组
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, byte[] byteArr) throws SftpException{
upload(directory, sftpFileName, new ByteArrayInputStream(byteArr));
}
/**
* 将字符串按照指定的字符编码上传到sftp
*
* @param directory
* 上传到sftp目录
* @param sftpFileName
* 文件在sftp端的命名
* @param dataStr
* 待上传的数据
* @param charsetName
* sftp上的文件,按该字符编码保存
* @throws UnsupportedEncodingException
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, String dataStr, String charsetName) throws UnsupportedEncodingException, SftpException{
upload(directory, sftpFileName, new ByteArrayInputStream(dataStr.getBytes(charsetName)));
}
/**
* 下载文件
*
* @param directory
* 下载目录
* @param downloadFile
* 下载的文件
* @param saveFile
* 存在本地的路径
* @throws SftpException
* @throws FileNotFoundException
* @throws Exception
*/
public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException{
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
File file = new File(saveFile);
sftp.get(downloadFile, new FileOutputStream(file));
log.info("file:{} is download successful" , downloadFile);
}
/**
* 下载文件
* @param directory 下载目录
* @param downloadFile 下载的文件名
* @return 字节数组
* @throws SftpException
* @throws IOException
* @throws Exception
*/
public byte[] download(String directory, String downloadFile) throws SftpException, IOException{
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
InputStream is = sftp.get(downloadFile);
byte[] fileData = IOUtils.toByteArray(is);
log.info("file:{} is download successful" , downloadFile);
return fileData;
}
/**
* 删除文件
*
* @param directory
* 要删除文件所在目录
* @param deleteFile
* 要删除的文件
* @throws SftpException
* @throws Exception
*/
public void delete(String directory, String deleteFile) throws SftpException{
if (isExist(directory,deleteFile)){
sftp.cd(directory);
sftp.rm(deleteFile);
log.info("file:{} is delete successful" , deleteFile);
}else {
log.info("file:{} is delete failure,because of file is not exist" , deleteFile);
}
}
/**
* 列出目录下的文件
*
* @param directory 要列出的目录
* @return
* @throws SftpException
*/
public Vector<?> listFiles(String directory) throws SftpException {
return sftp.ls(directory);
}
/**
* qy
* 判断是否存在该文件
* @param directory 路径
* @param fileName 文件名称
* @return
* @throws SftpException
*/
public boolean isExist(String directory, String fileName) throws SftpException {
return isExist(directory+"/"+fileName);
}
/**
* qy
* 判断是否存在该文件
* 文件不存在的话会抛 SftpException,e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE
* @param path 文件(绝对路径)
* @return
* @throws SftpException
*
*/
public boolean isExist(String path) throws SftpException {
boolean flag = false;
try {
sftp.stat(path);
flag = true;
}
catch (SftpException e){
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
log.info("path:{} is not exist" , path);
flag = false;
}
}
return flag;
}
/**
* Qy
* 修改文件名
* @param path 路径
* @param oldName 原始名称
* @param newName 修改名称
* @throws SftpException
*/
public boolean rename(String path, String oldName, String newName) throws SftpException{
boolean flag = false;
try {
System.out.println(path+"/"+oldName+"------->"+path+"/"+newName);
sftp.rename(path+"/"+oldName,path+"/"+newName);
flag = true;
log.info("old file name:[{}] rename to new file name:[{}] successful" , oldName, newName);
}
catch (SftpException e){
log.warn("old file name:[{}] is not exist or new file name:[{}] is exist" , oldName, newName);
flag = false;
}
return flag;
}
// 单元测试
/*public static void main(String[] args) throws SftpException, IOException {
SFTPConfigModel sftpConfigModel = new SFTPConfigModel().getDefaultConfig();
SFTPUtil sftp = new SFTPUtil(sftpConfigModel);
sftp.login();
File file = new File("D:\\inbound\\NCOMP_STHO_20201103_03_0001_CONTROL.txt");
InputStream is = new FileInputStream(file);
sftp.delete(sftpConfigModel.getUploadUrl(),"NCOMP_STHO_20201103_03_0001_CONTROL.txt");
sftp.upload(sftpConfigModel.getUploadUrl(), "NCOMP_STHO_20201103_03_0001_CONTROL.txt", is);
sftp.logout();
}*/
}
总结
以上就是使用时,本人编写的代码。如果各位需要,可以直接粘贴使用,有问题也可以留言哦!