引入pom依赖
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.1</version>
</dependency>
yml配置文件
logServer:
#文件AES加密需要的密钥
logSecretKey: uBdUx82vPHkDKb284d7NkjFoNcKWBuka
#文件暂存本地服务器目录
localLogPath: d:\\ftp\\gd
#目标服务器的ftp相关配置
ip: ***.***.***.***
port: **
username: ******
password: ******
basePath: /home/myftp
filePath: /TQGD
AES256工具类
public class AES256Util {
/**
* 密钥, 256位32个字节
*/
public static final String DEFAULT_SECRET_KEY = "uBdUx82vPHkDKb284d7NkjFoNcKWBuka";
private static final String AES = "AES";
/**
* 初始向量IV, 初始向量IV的长度规定为128位16个字节, 初始向量的来源为随机生成.
*/
private static final byte[] KEY_VI = "c558Gq0YQK2QUlMc".getBytes();
/**
* 加密解密算法/加密模式/填充方式
*/
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static java.util.Base64.Encoder base64Encoder = java.util.Base64.getEncoder();
private static java.util.Base64.Decoder base64Decoder = java.util.Base64.getDecoder();
static {
java.security.Security.setProperty("crypto.policy", "unlimited");
}
/**
* AES加密
*/
public static String encode(String key, String content) {
try {
javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(KEY_VI));
// 获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte[] byteEncode = content.getBytes(java.nio.charset.StandardCharsets.UTF_8);
// 根据密码器的初始化方式加密
byte[] byteAES = cipher.doFinal(byteEncode);
// 将加密后的数据转换为字符串
return base64Encoder.encodeToString(byteAES);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* AES解密
*/
public static String decode(String key, String content) {
try {
javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(KEY_VI));
// 将加密并编码后的内容解码成字节数组
byte[] byteContent = base64Decoder.decode(content);
// 解密
byte[] byteDecode = cipher.doFinal(byteContent);
return new String(byteDecode, java.nio.charset.StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String dbPassword = "123456";
String encryptDbPwd = AES256Util.encode(DEFAULT_SECRET_KEY, dbPassword);
System.out.println("encrypt: " + encryptDbPwd);
String decrypt = AES256Util.decode(DEFAULT_SECRET_KEY, encryptDbPwd);
System.out.println("decrypt:" + decrypt);
}
}
ftp工具类
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* @Author R0137 csy
* @Date 2022/11/7 14:12
*/
@Slf4j
public class FTPUtil {
/**
* Description: 向FTP服务器上传文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String host, int port, String username, String password, String basePath,
String filePath, String filename, InputStream input) {
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
log.info("ftp服务器登录失败!");
return false;
}
log.info("ftp服务器登录成功!");
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath+filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split(File.separator);
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath += File.separator + dir;
if (!ftp.changeWorkingDirectory(tempPath)) { //进不去目录,说明该目录不存在
if (!ftp.makeDirectory(tempPath)) { //创建目录
//如果创建文件目录失败,则返回
log.info("创建文件目录{}失败!",tempPath);
return false;
} else {
//目录存在,则直接进入该目录
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.setControlEncoding("UTF-8");
//ftp通信有两种模式
//PORT(主动模式)客户端开通一个新端口(>1024)并通过这个端口发送命令或传输数据,期间服务端只使用他开通的一个端口,例如21
//PASV(被动模式)客户端向服务端发送一个PASV命令,服务端开启一个新端口(>1024),并使用这个端口与客户端的21端口传输数据
//由于客户端不可控,防火墙等原因,所以需要由服务端开启端口,需要设置被动模式
ftp.enterLocalPassiveMode();
//上传文件,filename需要处理一下,不然中文的名字上传到ftp服务器是乱码的
if (!ftp.storeFile(new String(filename.getBytes(), StandardCharsets.ISO_8859_1), input)) {
return false;
}
input.close();
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return true;
}
/**
* Description: 从FTP服务器下载文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return
*/
public static boolean downloadFile(String host, int port, String username, String password, String remotePath,
String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath + File.separator + ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftp.retrieveFile(ff.getName(), is);
is.close();
}
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
//ftp上传文件测试main函数
public static void main(String[] args) {
//上传
try {
FileInputStream in=new FileInputStream(new File("d:\\ftp\\gd\\GD日志需求11.02.docx"));
boolean flag = uploadFile("192.168.2.124", 21, "myftp", "myftp", "/home/myftp","/TQGD", "GD日志需求11.02.docx", in);
System.out.println(flag);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//下载
boolean b = downloadFile("ip", 21, "username", "password", "/text/wenjian", "hello.txt", "D://");
System.out.println(b);
}
}
主程序
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.api.dto.LogVO;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.FTPUtil;
import org.jeecg.common.util.security.AES256Util;
import org.jeecg.modules.interlligence.mapper.SysLogMapper;
import org.jeecg.modules.interlligence.service.GDLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Value("${logServer.logSecretKey}")
private String logSecretKey;
@Value("${logServer.localLogPath}")
private String localLogPath;
@Value("${logServer.ip}")
private String ip;
@Value("${logServer.port}")
private int port;
@Value("${logServer.username}")
private String username;
@Value("${logServer.password}")
private String password;
@Value("${logServer.basePath}")
private String basePath;
@Value("${logServer.filePath}")
private String filePath;
@Autowired
private SysLogMapper sysLogMapper;
public void updateLogFileToServer(){
String formatStr = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter fmTime = DateTimeFormatter.ofPattern(formatStr);
LocalDateTime txtStart = LocalDateTime.now();
log.info("开始生成日志txt文件,开始时间:{}",txtStart.format(fmTime));
List<LogDTO> logList = sysLogMapper.getSysLogByTime(DateUtils.getLastNMinString(2 * 60,formatStr),DateUtils.getLastNMinString(0,formatStr));
log.info("日志数量为{}。",logList.size());
StringBuilder result = new StringBuilder();
for (LogDTO dto : logList) {
result.append(AES256Util.encode(logSecretKey, JSON.toJSONString(dto))).append("\n");
}
//生成txt文件到服务器本地
File file = new File(localLogPath);
if(!file.exists()){
file.mkdir();
}
String txtFileName = file + File.separator + System.currentTimeMillis() + ".txt";
try {
BufferedWriter out = new BufferedWriter(new FileWriter(txtFileName));
out.write(result.toString());
//把缓存区内容压入文件
out.flush();
out.close();
LocalDateTime txtEnd = LocalDateTime.now();
log.info("txt文件生成成功!开始压缩成zip文件。时间:{}",txtEnd.format(fmTime));
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDateTime zipFileDate = LocalDateTime.now();
String zipFileName = localLogPath + File.separator + System.currentTimeMillis() + zipFileDate.format(format) + ".zip";
File zipFile = new File(zipFileName);
FileOutputStream zipFileOut = new FileOutputStream(zipFile);
ZipOutputStream zipFileStream = new ZipOutputStream(zipFileOut);
byte[] buf = new byte[2048];
File textFile = new File(txtFileName);
zipFileStream.putNextEntry(new ZipEntry(textFile.getName()));
int len;
FileInputStream in = new FileInputStream(textFile);
while ((len = in.read(buf)) != -1){
zipFileStream.write(buf, 0, len);
}
zipFileStream.closeEntry();
in.close();
zipFileStream.close();
LocalDateTime zipEnd = LocalDateTime.now();
log.info("zip文件生成成功!开始上传ftp服务器。时间:{}",zipEnd.format(fmTime));
boolean uploadResult = FTPUtil.uploadFile(ip, port, username, password, basePath, filePath, zipFile.getName(), new FileInputStream(zipFile));
if(uploadResult){//如果成功,删除服务器产生的缓存文件
LocalDateTime zipUpload = LocalDateTime.now();
log.info("zip文件上传成功!时间:{}",zipUpload.format(fmTime));
textFile.delete();
zipFile.delete();
}else{//如果失败,留在服务器上
log.info("zip文件上传ftp服务器时发生错误,文件名:{}",zipFileName);
}
}catch (Exception e){
log.info("日志生成上传失败!--->"+e.getMessage());
}
}
遇到报错:java.security.InvalidKeyException: Illegal key size
参考https://blog.csdn.net/zhuwangxiangbie/article/details/105124612
https://blog.csdn.net/Linlietao0587/article/details/124823968
其中需要替换jre两个jar包,如果官网下载不下来,可以访问 https://wwi.lanzoup.com/iXGs404zm1dg(jdk8)