需求:通过SFTP读取加密文件并解析处理
1.SFTP工具类
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;
import java.util.Vector;
@Slf4j
@Component
public class SftpUtil {
static Session sshSession = null;
@Value("${sftp.username}")
private String username;
@Value("${sftp.password}")
private String password;
@Value("${sftp.server}")
private String server;
@Value("${sftp.port}")
private Integer port;
@Value(("${sftp.path}"))
private String path;
/**
* 获取ChannelSftp
*/
public ChannelSftp getConnectIP() {
log.info("获取实例开始,配置信息:username:{}, server:{}, port:{}", username, server, port);
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
jsch.getSession(username, server, port);
sshSession = jsch.getSession(username, server, port);
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
} catch (Exception e) {
e.printStackTrace();
}
log.info("获取sftp实例完成");
return sftp;
}
public List<String> AnalysisFile(String pathName, String charset) {
ChannelSftp connectIP = getConnectIP();
BufferedReader reader = null;
List<String> ls = new ArrayList<>();
try {
reader = new BufferedReader(new InputStreamReader(connectIP.get(pathName),charset));
String str;
while((str = reader.readLine()) != null) {
ls.add(str);
}
reader.close();
return ls;
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
disconnect(connectIP);
}
}
public static void main(String[] args) {
}
/**
* 遍历远程文件
*
* @param remotePath
* @return
* @throws Exception
*/
public List<String> listFiles(String remotePath){
List<String> ftpFileNameList = new ArrayList<String>();
ChannelSftp.LsEntry isEntity = null;
String fileName = null;
ChannelSftp sftp = null;
try{
sftp = connect();
if(sftp == null){
return null;
}
Vector<ChannelSftp.LsEntry> sftpFile = sftp.ls(remotePath);
Iterator<ChannelSftp.LsEntry> sftpFileNames = sftpFile.iterator();
while (sftpFileNames.hasNext()) {
isEntity = (ChannelSftp.LsEntry) sftpFileNames.next();
fileName = isEntity.getFilename();
//约定好文件名称
if(fileName.startsWith("end")){
ftpFileNameList.add(fileName);
}
}
return ftpFileNameList;
}catch (Exception e){
log.error("遍历查询sftp服务器上文件异常",e);
return null;
}finally {
disconnect(sftp);
}
}
/**
* 连接登陆远程服务器
*
* @return
*/
public ChannelSftp connect() {
JSch jSch = new JSch();
Session session = null;
ChannelSftp sftp = null;
try {
session = jSch.getSession(username, server, port);
session.setPassword(password);
session.setConfig(getSshConfig());
session.connect();
sftp = (ChannelSftp)session.openChannel("sftp");
sftp.connect();
log.error("结果:"+session.equals(sftp.getSession()));
log.info("登录成功:" + sftp.getServerVersion());
} catch (Exception e) {
log.error("SSH方式连接FTP服务器时有JSchException异常!",e);
return null;
}
return sftp;
}
/**
* 获取服务配置
* @return
*/
private static Properties getSshConfig() {
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
return sshConfig;
}
boolean deleteDirFiles(String newsFile, ChannelSftp sftp) {
try {
sftp.cd(newsFile);
ListIterator a = sftp.ls(newsFile).listIterator();
while (a.hasNext()) {
ChannelSftp.LsEntry oj = (ChannelSftp.LsEntry) a.next();
delete(newsFile, oj.getFilename(), sftp);
//fileList.add((String) a.next());
}
} catch (Exception e) {
e.getMessage();
}
return false;
}
public boolean isExistDir(String path, ChannelSftp sftp) {
boolean isExist = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(path);
isExist = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if ("no such file".equalsIgnoreCase(e.getMessage())) {
isExist = false;
}
}
return isExist;
}
/**
* 查看
*/
public List<String> check(String directory, ChannelSftp sftp) {
List<String> fileList = new ArrayList<>();
try {
sftp.cd(directory);
ListIterator a = sftp.ls(directory).listIterator();
while (a.hasNext()) {
ChannelSftp.LsEntry oj = (ChannelSftp.LsEntry) a.next();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sftp.isConnected()) {
sshSession.disconnect();
sftp.disconnect();
}
}
return fileList;
}
/**
* 删除
*/
public void delete(String directory, String deleteFile, ChannelSftp sftp) {
try {
log.info("开始删除:"+deleteFile);
sftp.cd(directory);
sftp.rm(deleteFile);
log.info("删除完成:"+deleteFile);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载远程sftp服务器文件
*
* @return
*/
public void downloadFile(String remoteFilename,File localFile) {
FileOutputStream output = null;
ChannelSftp sftp = getConnectIP();
try {
if(sftp == null){
return ;
}
output = new FileOutputStream(localFile);
sftp.get(remoteFilename, output);
log.info("成功接收文件,本地路径:[{}]" + localFile.getAbsolutePath());
output.close();
} catch (Exception e) {
log.error("接收文件异常!",e);
} finally {
try {
if (null != output) {
output.flush();
output.close();
}
// 关闭连接
disconnect(sftp);
} catch (IOException e) {
log.error("关闭文件时出错!",e);
}
}
}
/**
* 关闭连接
* @param sftp
*/
public void disconnect(ChannelSftp sftp) {
try {
if(sftp!=null){
if(sftp.getSession().isConnected()){
sftp.getSession().disconnect();
}
}
} catch (Exception e) {
log.error("关闭与sftp服务器会话连接异常",e);
}
}
}
2.文件解析处理
本地测试用测试发版改来改去比较麻烦。所以文件解析写了两套,一套用于生产,从SFTP上读取的是加密的文件信息;另一套作为本地测试使用,读取本地的文件路径,读取的是解密过的文件,即明文。
//拼接日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
String path = "/1nx/" + dateFormat.format(new Date());
log.info("读取文件路径:{}", path);
BufferedReader bufferedReader = null;
InputStreamReader read = null;
String env = evn.getProperty("spring.profiles.active");
if (Objects.equals(env, "prod")) {
List<String> files = sftpUtil.listFiles(path);
log.info("打印从SFTP获取到的所有文件名:{}",StringUtils.join(files,","));
//获取当前文件夹下所有文件
for (String fileName : files) {
log.info("当前文件信息为:{}", fileName);
//文件读取,并获取每一条数据 // StandardCharsets.UTF_8
log.info("打印读取文件的全路径:{}",path + File.separator + fileName);
List<String> stringList = sftpUtil.AnalysisFile(path + File.separator + fileName, "GBK");
//获取之后,属于加密文件,需要对每条进行解密操作 排除第一条 第一条属于对应字段名称
log.info("开始对文件里的数据进行解密处理,该文件里数据总条数为:{}条", stringList.size()-1);
for (int i = 1; i < stringList.size(); i++) {
String anaysis = RsaUtil.decryptStr(stringList.get(i));
log.info("本条解析后的报文为:{}",anaysis);
}
}
} else {
File fileLogFiles = new File("C:" + path);
//本地环境 遍历主盘该路径下所有文件
File[] files = fileLogFiles.listFiles();
for (File file : files) {
//拼接文件完整路径
String fileNamePath = "C:" + path + File.separator + file.getName();
FileInputStream fileInputStream = new FileInputStream(new File(fileNamePath));
read = new InputStreamReader(fileInputStream, "utf-8");
bufferedReader = new BufferedReader(read);
String line = null;
List<String> lineList = new ArrayList<>();
int count = 0;
while ((line = bufferedReader.readLine()) != null) {
lineList.add(line);
//本地是源文件,不需要解密操作 跳过第一行
if (count == 0) {
count++;
continue;
}
}
}
}
//开始对解析出的数据集合进行处理
log.info("开始对解析出的数据集合进行处理");
// LIST集合转json字符串 SerializerFeature.WriteNullStringAsEmpty为NULL转空字符串
String string = JSONObject.toJSONString(analysisFtpToSxBoList, SerializerFeature.WriteNullStringAsEmpty);