Browse Source

适配江西万象山接集控 通过sftp去对端下载修正短期文件及解析功能

fanxiaoyu 1 năm trước cách đây
mục cha
commit
ccd56a93fb

+ 14 - 0
in-passback/pom.xml

@@ -79,6 +79,20 @@
             <scope>compile</scope>
         </dependency>
 
+        <!--SFTP-->
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId>
+            <version>0.1.55</version>
+        </dependency>
+        <!--SFTP-->
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.8.0</version> <!-- 请使用最新的稳定版本 -->
+        </dependency>
+
     </dependencies>
 
     <build>

+ 7 - 1
in-passback/src/main/java/com/jiayue/passback/entity/eunm/PredictionModelEnum.java

@@ -34,7 +34,13 @@ public enum PredictionModelEnum {
 	// 人工干预系数
 	E10(10, "干预系数模型"),
 
-	E11(11,"一体化修正形");
+	E11(11,"一体化修正形"),
+
+	E12(12,"大风切机修正"),
+
+	E13(13,"超短期算法模型"),
+
+	E14(14,"集中功率预测修正");
 	private Integer code;
 	private String message;
 }

+ 219 - 0
in-passback/src/main/java/com/jiayue/passback/job/analysisJob.java

@@ -0,0 +1,219 @@
+package com.jiayue.passback.job;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.jiayue.passback.entity.ForecastPowerShortTerm;
+import com.jiayue.passback.entity.eunm.PredictionModelEnum;
+import com.jiayue.passback.mapper.ForecastPowerShortTermMapper;
+import com.jiayue.passback.service.ForecastPowerShortTermService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+/**
+ * 解析修正短期数据定时任务
+ */
+@Component
+@Slf4j
+public class analysisJob {
+
+    private final ForecastPowerShortTermMapper forecastPowerShortTermMapper;
+
+    private final ForecastPowerShortTermService forecastPowerShortTermService;
+
+
+    public analysisJob(ForecastPowerShortTermMapper forecastPowerShortTermMapper, ForecastPowerShortTermService forecastPowerShortTermService) {
+        this.forecastPowerShortTermMapper = forecastPowerShortTermMapper;
+        this.forecastPowerShortTermService = forecastPowerShortTermService;
+    }
+
+    @Scheduled(cron = "0 0/1 * * * ?")
+    public void analysisShortTerm() {
+        log.info("-----------------------解析修正短期数据定时任务开始执行-----------------------");
+        String dayStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
+
+        // 扫描路径
+        String scanPath = "/home/syjy/backFile" + File.separator;
+
+        String newPath = scanPath + "new" + File.separator;
+
+        String bak = scanPath + "bak" +File.separator +  dayStr + File.separator;
+
+        String error = scanPath + "error" + File.separator;
+
+
+        File bakFile = new File(bak);
+
+        File errorFile = new File(error);
+
+        File newFile = new File(newPath);
+
+
+        // 判断目录是否存在
+        if (!bakFile.exists()) {
+            bakFile.mkdirs();
+            log.info("【" + bakFile.getPath() + "】目录不存在,系统自动创建文件目录");
+        }
+
+        if (!errorFile.exists()) {
+            errorFile.mkdirs();
+            log.info("【" + errorFile.getPath() + "】目录不存在,系统自动创建文件目录");
+        }
+
+        if (!newFile.exists()) {
+            newFile.mkdirs();
+            log.info("【" + newFile.getPath() + "】目录不存在,系统自动创建文件目录");
+        }
+
+        log.info("系统扫描路径【" + newFile.getPath() + "】");
+
+        Collection<File> files = FileUtils.listFiles(newFile, new String[]{"CIME"}, false);
+
+
+        if (files.size() > 0) {
+            for (File file : files) {
+                if (!file.getName().contains(dayStr)) {
+                    file.delete();
+                    log.warn(file.getName() + "不是当天文件,系统自动删除!");
+                    break;
+                }
+                log.info("开始解析文件【" + file.getName() + "】");
+                List<ForecastPowerShortTerm> forecastPowerShortTermList = fileAnalysisShortTerm(file, new Date().getTime());
+                if (null != forecastPowerShortTermList && forecastPowerShortTermList.size() > 0) {
+                    this.updateShortTerm(forecastPowerShortTermList);
+                    log.info("短期数据更新成功!文件记录数" + forecastPowerShortTermList.size() + "条");
+                    try {
+                        FileUtils.moveFile(new File(newFile + File.separator + file.getName()), new File(bakFile + File.separator + file.getName()));
+                        log.info("文件【" + file.getName() + "】移动到bak目录成功!");
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                } else {
+                    try {
+                        FileUtils.moveFile(new File(newFile + File.separator + file.getName()), new File(errorFile + File.separator + file.getName()));
+                        log.warn("文件内容为空,不进行数据更新!移动到失败目录下");
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+
+    }
+
+
+    /**
+     * 更新数据
+     *
+     * @param shortTermList
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void updateShortTerm(List<ForecastPowerShortTerm> shortTermList) {
+        // 获取明天开始时间和结束时间
+        long startTime = shortTermList.get(0).getForecastTime();
+        long endTime = shortTermList.get(shortTermList.size() - 1).getForecastTime();
+        // 根据开始时间和结束时间作为删除的查询条件
+        LambdaQueryWrapper<ForecastPowerShortTerm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.between(ForecastPowerShortTerm::getForecastTime, startTime, endTime);
+        shortTermList.sort(Comparator.comparing(ForecastPowerShortTerm::getForecastTime));
+        // 删除明天的预测数据
+        forecastPowerShortTermMapper.delete(lambdaQueryWrapper);
+        // 保存明天的预测数据
+        forecastPowerShortTermService.saveBatch(shortTermList);
+    }
+
+
+    private List<ForecastPowerShortTerm> fileAnalysisShortTerm(File file, Long currentDate) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
+        List<ForecastPowerShortTerm> forecastPowerShortTerm = new ArrayList<>();
+        // 当文件未被使用时,进行解析上报
+        if (file.renameTo(file)) {
+            InputStreamReader read = null;
+            BufferedReader bufferedReader = null;
+            String stringLine;
+            ForecastPowerShortTerm stf;
+            try {
+                read = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
+                bufferedReader = new BufferedReader(read);
+                // 循环解析文件
+                while ((stringLine = bufferedReader.readLine()) != null) {
+                    String[] string_arr = stringLine.split(" ");
+                    if (string_arr.length == 12 && string_arr[0].startsWith("#")) {
+                        if (StringUtils.isNotEmpty(string_arr[2])) {
+                            stf = new ForecastPowerShortTerm();
+                            stf.setFpValue(new BigDecimal(string_arr[3]));
+                            stf.setForecastTime(sdf.parse(string_arr[2]).getTime());
+                            stf.setGenDate(new Date(currentDate));
+                            stf.setPredictionModelEnum(PredictionModelEnum.E14);
+                            forecastPowerShortTerm.add(stf);
+                        }
+                    }
+                }
+            } catch (IOException | ParseException | RuntimeException e) {
+                log.error("系统错误:", e);
+                File destFile = new File(file.getPath().replaceFirst("new", "error"));
+                if (destFile.exists()) {
+                    destFile.delete();
+                }
+                try {
+                    FileUtils.moveFile(file, destFile);
+                } catch (IOException e1) {
+                    log.error(file.getName() + "文件解析失败", e);
+                }
+            } finally {
+                close(bufferedReader, read);
+            }
+        }
+        return forecastPowerShortTerm;
+    }
+
+    private void close(BufferedReader bufferedReader, InputStreamReader read) {
+        try {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+            if (read != null) {
+                read.close();
+            }
+        } catch (IOException e) {
+            log.error("关闭文件流失败:", e);
+        }
+    }
+
+
+//    private void moveFileBackups(String filePath) {
+//        String targetRoot = filePath.replaceFirst("backupsTemp", "backups");
+//        // 移动文件夹内容
+//        File sourceFile = new File(filePath);
+//        if (sourceFile.exists()) {
+//            try {
+//                File[] files = sourceFile.listFiles();
+//                if (files != null) {
+//                    for (File f : files) {
+//                        if (f.renameTo(new File(path + f.getName()))) {
+//                            log.info("move file :{}, dest file:{}", path, f.getName());
+//                        }
+//                    }
+//                }
+//            } catch (Exception e) {
+//                log.error("文件移动失败" + e);
+//            }
+//        }
+//    }
+
+}

+ 1 - 1
in-passback/src/main/java/com/jiayue/passback/job/job.java

@@ -19,7 +19,7 @@ public class job extends GenerateService {
 
     private final ElectricFieldService electricFieldService;
 
-    @Scheduled(cron = "${job.cdqjob}")
+//    @Scheduled(cron = "${job.cdqjob}")
     @Override
     public void GenerateData() {
         try {

+ 63 - 0
in-passback/src/main/java/com/jiayue/passback/job/sftpJob.java

@@ -0,0 +1,63 @@
+package com.jiayue.passback.job;
+
+import com.jiayue.passback.constants.CommonStant;
+import com.jiayue.passback.entity.SysParameter;
+import com.jiayue.passback.service.SystemParameterService;
+import com.jiayue.passback.util.SFTPUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+
+@Slf4j
+@Component
+public class sftpJob {
+
+    private final SystemParameterService systemParameterService;
+    public sftpJob(SystemParameterService systemParameterService){
+        this.systemParameterService =systemParameterService;
+    }
+    // 去对端拿文件parameter
+    @Scheduled(cron = "0 0/1 * * * ?")
+	public void sftpJob(){
+        log.info("---------------------开始执行sftp下载文件定时任务---------------------");
+        SysParameter parameter  = systemParameterService.getParameter();
+        String sftpParameter =parameter.getSysValue();
+        // 根据用户名获取密码
+        String host = sftpParameter.split(CommonStant.CHARACTER_COLON)[0];
+        String userName = sftpParameter.split(CommonStant.CHARACTER_COLON)[1];
+        String password = sftpParameter.split(CommonStant.CHARACTER_COLON)[2];
+        int port = Integer.valueOf(sftpParameter.split(CommonStant.CHARACTER_COLON)[3]);
+        String path = sftpParameter.split(CommonStant.CHARACTER_COLON)[4];
+        String savePath = sftpParameter.split(CommonStant.CHARACTER_COLON)[5];
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+        String dayStr = dateFormat.format(new Date());
+        // 查询当前文件是否已经下载过
+        String bakPath = savePath.replace("new", "bak"+File.separator + dayStr);
+
+        File filePath = new File(bakPath);
+        if (!filePath.exists()){
+            filePath.mkdirs();
+            log.info("扫描文件夹不存在,系统自动创建该文件夹!");
+        }
+        Collection<File> files = FileUtils.listFiles(filePath, new String[]{"CIME"}, false);
+        if (files.size() > 0){
+         for (File file : files){
+             if (file.getName().contains(dayStr)) {
+                 log.info("已经下载过该文件,无需再次下载");
+                 continue;
+             }
+             SFTPUtil.loginAndDownload(userName, password,host,port,path,savePath);
+         }
+        }else {
+            SFTPUtil.loginAndDownload(userName, password,host,port,path,savePath);
+        }
+
+        log.info("-----------------------sftp执行下载定时任务完成----------------------");
+	}
+}

+ 1 - 0
in-passback/src/main/java/com/jiayue/passback/service/SystemParameterService.java

@@ -4,4 +4,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.jiayue.passback.entity.SysParameter;
 
 public interface SystemParameterService extends IService<SysParameter> {
+    SysParameter getParameter();
 }

+ 20 - 0
in-passback/src/main/java/com/jiayue/passback/service/impl/SystemParameterServiceImpl.java

@@ -1,15 +1,35 @@
 package com.jiayue.passback.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.passback.constants.CommonStant;
 import com.jiayue.passback.entity.ElectricField;
 import com.jiayue.passback.entity.SysParameter;
 import com.jiayue.passback.mapper.ElectricFieldMapper;
 import com.jiayue.passback.mapper.SystemParameterMapper;
 import com.jiayue.passback.service.ElectricFieldService;
 import com.jiayue.passback.service.SystemParameterService;
+import com.jiayue.passback.util.JsonResultUtil;
 import org.springframework.stereotype.Service;
 
 @Service
 public class SystemParameterServiceImpl extends ServiceImpl<SystemParameterMapper, SysParameter> implements SystemParameterService {
 
+    private final SystemParameterMapper systemParameterMapper;
+
+    public SystemParameterServiceImpl(SystemParameterMapper systemParameterMapper){
+        this.systemParameterMapper = systemParameterMapper;
+    }
+    @Override
+    public SysParameter getParameter() {
+        // 设置参数
+        QueryWrapper<SysParameter> wrapper = new QueryWrapper();
+        wrapper.eq("C_SYS_KEY", "SFTP_PARAMETER");
+        SysParameter systemParameter = systemParameterMapper.selectOne(wrapper);
+        if (systemParameter == null || systemParameter.getSysValue() == null || "".equals(systemParameter.getSysValue()) || systemParameter.getSysValue().split(CommonStant.CHARACTER_COLON).length != 6) {
+            log.error("系统参数SFTP_PARAMETER未配置或配置错误");
+            return null;
+        }
+        return systemParameter;
+    }
 }

+ 442 - 0
in-passback/src/main/java/com/jiayue/passback/util/SFTPUtil.java

@@ -0,0 +1,442 @@
+package com.jiayue.passback.util;
+
+import com.jcraft.jsch.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.springframework.stereotype.Component;
+
+import java.io.*;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * @description:
+ * @author: 张成龙
+ * @createDate: 2021/9/27
+ * @version: 1.0
+ */
+@Component
+@Slf4j
+public class SFTPUtil {
+
+    private ChannelSftp sftp;
+
+    private Session session;
+
+    // SFTP 登录用户名
+    private String userName;
+    // SFTP 登录密码
+    private String password;
+    // SFTP 服务器地址IP地址
+    private String host;
+    // SFTP 端口
+    private int port;
+
+    /**
+     * 构造基于密码认证的sftp对象
+     *
+     * @param userName
+     * @param password
+     * @param host
+     * @param port
+     */
+    public SFTPUtil(String userName, String password, String host, int port) {
+        this.userName = userName;
+        this.password = password;
+        this.host = host;
+        this.port = port;
+    }
+
+    public SFTPUtil() {
+    }
+
+    /**
+     * 连接sftp服务器
+     *
+     * @throws Exception
+     */
+    public String login(String path) {
+        String fileName = null;
+        try {
+            JSch jsch = new JSch();
+            log.info("sftp连接host:{} username:{}", host, userName);
+
+            session = jsch.getSession(userName, host, port);
+            log.info("Session is build");
+            if (password != null) {
+                session.setPassword(password);
+            }
+
+            // 设置超时连接50秒
+            session.setTimeout(50000);
+
+            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 successful", host, port));
+
+            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
+
+            String date = simpleDateFormat.format(new Date());
+
+            log.info("当天日期为"+date);
+
+            try {
+                // 遍历指定路径
+                Vector<ChannelSftp.LsEntry> fileList = ((ChannelSftp) channel).ls(path);
+                // 获取文件列表
+                for (ChannelSftp.LsEntry entry : fileList) {
+                    if (!entry.getAttrs().isDir()) {
+                        if (entry.getFilename().contains(date)) {
+                            fileName = entry.getFilename();
+                            log.info("找到文件"+fileName);
+                        }else {
+                            log.info("没有找到包含当天日期的文件");
+                        }
+                    }
+                }
+
+            } catch (SftpException e) {
+                throw new RuntimeException(e);
+            }
+        } catch (JSchException e) {
+            log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
+        }
+        return fileName;
+    }
+
+    /**
+     * 关闭连接 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");
+            }
+        }
+    }
+
+    /**
+     * 递归根据路径创建文件夹
+     *
+     * @param dirs     根据 / 分隔后的数组文件夹名称
+     * @param tempPath 拼接路径
+     * @param length   文件夹的格式
+     * @param index    数组下标
+     * @return
+     */
+    public void mkdirDir(String[] dirs, String tempPath, int length, int index) {
+        // 以"/a/b/c/d"为例按"/"分隔后,第0位是"";顾下标从1开始
+        index++;
+        if (index < length) {
+            // 目录不存在,则创建文件夹
+            tempPath += "/" + dirs[index];
+        }
+        try {
+            log.info("检测目录[" + tempPath + "]");
+            sftp.cd(tempPath);
+            if (index < length) {
+                mkdirDir(dirs, tempPath, length, index);
+            }
+        } catch (SftpException ex) {
+            log.warn("创建目录[" + tempPath + "]");
+            try {
+                sftp.mkdir(tempPath);
+                sftp.cd(tempPath);
+            } catch (SftpException e) {
+                e.printStackTrace();
+                log.error("创建目录[" + tempPath + "]失败,异常信息[" + e.getMessage() + "]");
+
+            }
+            log.info("进入目录[" + tempPath + "]");
+            mkdirDir(dirs, tempPath, length, index);
+        }
+    }
+
+    /**
+     * 将输入流的数据上传到sftp作为文件(多层目录)
+     *
+     * @param directory    上传到该目录(多层目录)
+     * @param sftpFileName sftp端文件名
+     * @param input        输入流
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void uploadMore(String directory, String sftpFileName, InputStream input) throws SftpException {
+        try {
+            sftp.cd(directory);
+        } catch (SftpException e) {
+            // 目录不存在,则创建文件夹
+            String[] dirs = directory.split("/");
+            String tempPath = "";
+            int index = 0;
+            mkdirDir(dirs, tempPath, dirs.length, index);
+        }
+        sftp.put(input, sftpFileName);// 上传文件
+    }
+
+    /**
+     * 将输入流的数据上传到sftp作为文件
+     *
+     * @param directory    上传到该目录(单层目录)
+     * @param sftpFileName sftp端文件名
+     * @param input        输入流
+     * @throws SftpException
+     * @throws Exception
+     */
+    public void upload(String directory, String sftpFileName, InputStream input) {
+        try {
+            // 切换路径
+            sftp.cd(directory);
+        } catch (SftpException e) {
+            log.warn(directory + ":directory is not exist");
+            try {
+                // 循环创建路径
+                this.createParentDirectories(sftp, directory);
+                // 切换路径
+                sftp.cd(directory);
+            } catch (SftpException e1) {
+                log.warn("sftp文件路径异常" + e1.toString());
+                return;
+            }
+        }
+        try {
+            sftp.put(input, sftpFileName);
+            log.info("file:{} is upload successful", sftpFileName);
+        } catch (SftpException e) {
+            log.warn("文件传输异常" + e.toString());
+            return;
+        }
+    }
+
+    /**
+     * 上传单个文件
+     *
+     * @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);
+            log.info("进入"+directory+"目录下");
+        }else {
+            log.info("没有找到指定目录");
+        }
+        FileOutputStream fos = null;
+        try {
+            fos = new FileOutputStream(saveFile);
+            sftp.get(downloadFile, fos);
+            log.info("file:{} 文件下载成功!", downloadFile);
+        } catch (Exception e) {
+            // 处理异常
+            log.error("文件下载失败", e);
+            throw e;
+        } finally {
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    // 记录关闭流时的异常
+                    log.error("关闭文件输出流时发生异常", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * 下载文件
+     *
+     * @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 {
+        sftp.cd(directory);
+        sftp.rm(deleteFile);
+    }
+
+    /**
+     * 列出目录下的文件
+     *
+     * @param directory 要列出的目录
+     * @return
+     * @throws SftpException
+     */
+    public Vector<?> listFiles(String directory) throws SftpException {
+        return sftp.ls(directory);
+    }
+
+//    public static void main(String[] args) throws SftpException, IOException {
+//        SFTPUtil sftp = new SFTPUtil("jyzx2023", "hH6*7E$h", "114.115.165.178", 22);
+//        sftp.login();
+//        File file = new File("..\\sftp测试.txt");
+//        log.info(System.getProperty("user.dir"));
+//        InputStream is = new FileInputStream(file);
+//        // 多级目录创建并上传
+//        sftp.upload("/subdata/20230712/real", "sftp测试.txt", is);
+//        sftp.logout();
+//    }
+
+    /**
+     * 多级目录创建并上传
+     * @param userName
+     * @param password
+     * @param host
+     * @param port
+     * @param file
+     * @throws SftpException
+     * @throws FileNotFoundException
+     */
+//    public void uploadByFileAndPath(String userName, String password, String host, int port, File file, String sftpFilePath, String fileName) {
+//        SFTPUtil sftp = new SFTPUtil(userName, password, host, port);
+//        sftp.login();
+//        log.info(System.getProperty("user.dir"));
+//        try {
+//            InputStream is = new FileInputStream(file);
+//            // 多级目录创建并上传
+//            sftp.upload(sftpFilePath, fileName, is);
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        sftp.logout();
+//    }
+
+    /**
+     * 登录并下载所需文件
+     *
+     * @param userName
+     * @param password
+     * @param host
+     * @param port
+     * @param sftpFilePath
+     */
+    public static void loginAndDownload(String userName, String password, String host, int port, String sftpFilePath,String savePath) {
+        SFTPUtil sftp = new SFTPUtil(userName, password, host, port);
+
+        String fileName = sftp.login(sftpFilePath);
+
+        try {
+            if (null != fileName) {
+                // 下载文件
+                sftp.download(sftpFilePath, fileName, savePath+File.separator+fileName);
+            } else {
+                log.error("没有找到所需文件");
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        sftp.logout();
+        log.info("下载完成关闭断开Sftp");
+    }
+
+
+    /**
+     * 循环创建路径
+     *
+     * @param sftpChannel
+     * @param directory
+     */
+    private static void createParentDirectories(ChannelSftp sftpChannel, String directory) {
+        String[] directories = directory.split("/");
+        String parentDirectory = "";
+
+        for (String dir : directories) {
+            if (!dir.isEmpty()) {
+                parentDirectory += "/" + dir;
+                try {
+                    sftpChannel.mkdir(parentDirectory);
+                } catch (Exception e) {
+                    // 目录已存在,忽略异常
+                }
+            }
+        }
+        log.info("创建路径:" + parentDirectory);
+    }
+
+}