How does springboot read the files of sftp

  • 2021-12-12 08:40:38
  • OfStack

Directory springboot reads sftp file 1. Add pom dependency (based on springboot project) 2. application. yaml configuration file 3. Tool class 4. Actual call springboot uploads using SFTP file

springboot reads the file of sftp

1. Add an pom dependency (based on the springboot project)


<dependency>  
     <groupId>com.jcraft</groupId>  
     <artifactId>jsch</artifactId>  
     <version>0.1.54</version>  
   </dependency>

2. application. yaml configuration file


sftp:
   ip: 192.168.1.102
   port: 22
   username: admin
   password: admin
   root: /img # File root directory 

3. Tool classes


import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import lombok.extern.slf4j.Slf4j;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
 
/**
 *
 */
@Slf4j
public class SFTPUtil {
 
    /**
     *  Download retries 
     */
    private static final int DOWNLOAD_RETRY = 3;
 
    /**
     *  Download retry interval   Unit millisecond 
     */
    private static final long DOWNLOAD_SLEEP = 3 * 1000; 
    private static final SFTPUtil SFTP = new SFTPUtil();
    private static ChannelSftp client;
    private static Session session;
 
    /**
     * @return
     */
    public static SFTPUtil getInstance() {
        return SFTP;
    }
 
    /**
     *  Get SFTP Connect 
     *
     * @param username
     * @param password
     * @param ip
     * @param port
     * @return
     */
    synchronized public ChannelSftp makeConnection(String username, String password, String ip, int port) {
        if (client == null || session == null || !client.isConnected() || !session.isConnected()) {
            try {
                JSch jsch = new JSch();
                session = jsch.getSession(username, ip, port);
                if (password != null) {
                    session.setPassword(password);
                }
                Properties config = new Properties();
                //  Set the 1 Host public key confirmation prompt when logging in for the second time, optional value: (ask | yes | no)
                config.put("StrictHostKeyChecking", "no");
                session.setConfig(config);
                session.connect();
                //sftp Agreement 
                Channel channel = session.openChannel("sftp");
                channel.connect();
                client = (ChannelSftp) channel;
                log.info("sftp connected success , connect to [{}:{}], username [{}]", ip, port, username);
            } catch (JSchException e) {
                log.error("sftp connected fail , connect to [{}:{}], username [{}], password [{}], error message : [{}]", ip, port, username, password, e.getMessage());
            } 
        }
        return client;
    }
 
    /**
     *  
     *  Close the connection  server 
     */
    public static void close() {
        if (client != null && client.isConnected()) {
            client.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        } 
    } 
    /**
     *  Single download file 
     *
     * @param downloadFile  Download file address 
     * @param saveFile      Save file address 
     * @param ip            Host address 
     * @param port          Host port 
     * @param username      User name 
     * @param password      Password 
     * @param rootPath      Root directory 
     * @return
     */
    public synchronized static File download(String downloadFile, String saveFile, String ip, Integer port, String username, String password, String rootPath) {
        boolean result = false;
        File file = null;
        Integer i = 0;
        while (!result) {
            // Get a connection 
            ChannelSftp sftp = getInstance().makeConnection(username, password, ip, port);
            FileOutputStream fileOutputStream = null;
            log.info("sftp file download start, target filepath is {}, save filepath is {}", downloadFile, saveFile);
            try {
                sftp.cd(rootPath);
                file = new File(saveFile);
                if (file.exists()) {
                    file.delete();
                } else {
                    file.createNewFile();
                }
                fileOutputStream = new FileOutputStream(file);
                sftp.get(downloadFile, fileOutputStream);
                result = true;
            } catch (FileNotFoundException e) {
                log.error("sftp file download fail, FileNotFound: [{}]", e.getMessage());
            } catch (IOException e) {
                log.error("sftp file download fail, IOException: [{}]", e.getMessage());
            } catch (SftpException e) {
                i++;
                log.error("sftp file download fail, sftpException: [{}]", e.getMessage());
                if (i > DOWNLOAD_RETRY) {
                    log.error("sftp file download fail, retry three times, SftpException: [{}]", e.getMessage());
                    return file;
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(DOWNLOAD_SLEEP);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            } finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            SFTPUtil.close();
 
        }
        return file;
    } 
    /**
     *  Download a file 
     *
     * @param downloadFile  The path to download the file 
     * @param saveFile      Saved path 
     * @param rootPath      Root directory 
     * @return
     */
    public synchronized static File download(String downloadFile, String saveFile, String rootPath) {
        boolean result = false;
        File file = null;
        Integer i = 0;
        while (!result) {
            FileOutputStream fileOutputStream = null;
            log.info("sftp file download start, target filepath is {}, save filepath is {}", downloadFile, saveFile);
            try {
                // Get the connection and read the file (ChannelSftp) session.openChannel("sftp")
                client.cd(rootPath);
                file = new File(saveFile);
                if (file.exists()) {
                    file.delete();
                } else {
                    file.createNewFile();
                }
                fileOutputStream = new FileOutputStream(file);
                client.get(downloadFile, fileOutputStream);
                result = true;
            } catch (FileNotFoundException e) {
                log.error("sftp file download fail, FileNotFound: [{}]", e.getMessage());
            } catch (IOException e) {
                log.error("sftp file download fail, IOException: [{}]", e.getMessage());
            } catch (SftpException e) {
                i++;
                log.error("sftp file download fail, sftpException: [{}]", e.getMessage());
                if (i > DOWNLOAD_RETRY) {
                    log.error("sftp file download fail, retry three times, SftpException: [{}]", e.getMessage());
                    return file;
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(DOWNLOAD_SLEEP);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            } finally {
                try {
                    if (fileOutputStream != null) {
                        fileOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } 
        }
        return file;
    }  
}

4. Actual call


public class SFTP { 
    @Value("${sftp.ip}")
    String ip;
 
    @Value("${sftp.port}")
    Integer port;
 
    @Value("${sftp.username}")
    String username;
 
    @Value("${sftp.password}")
    String password;
 
    @Value("${sftp.root}")
    String rootPath;
 
     @GetMapping("/test")
    public void test() throws IOException {
        SFTPUtil.getInstance().makeConnection(username, password, ip, port);
        File file= SFTPUtil.download(downloadFilePath, "1.txt", rootPath);
        SFTPUtil.close();
        InputStreamReader read = null;
        BufferedReader bufferedReader = null;
        String encoding = "utf-8";
        try {
            read = new InputStreamReader(new FileInputStream(file), encoding);
            bufferedReader = new BufferedReader(read);
            String lineTxt = null;
            while ((lineTxt = bufferedReader.readLine()) != null) {
                log.info("[{}] downfile is [{}] ", username, lineTxt);
                }
            read.close();
            bufferedReader.close();
            file.delete();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (read != null) {
                    read.close();
                }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (file != null && file.exists()) {
                    file.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } 
    }  
}

springboot Upload Using SFTP File

Recently, I used sftp to upload and download files in my work function. Here, I simply record 1

The related jar package is introduced into the pom file


        <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>

Establish the springboot project and add the following configuration to application. properties


sftp.ip=127.0.0.1
sftp.port=22
sftp.username=xuyy
sftp.password=paswpord
#ftp Root directory 
sftp.rootpath="D:SFTP/

The configuration at the beginning of 1sftp above is user-defined. You need to write a configuration class to read 1 and inject it into springboot automatically


package com.uinnova.ftpsynweb.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 *  Features:   Read the configuration file. You can assign values directly to static variables 
 *
 * @author xuyangyang
 */
@Component
@ConfigurationProperties(prefix = "sftp")
@Data
public class SftpConfig {
    public static String ip;
    public static Integer port;
    public static String username;
    public static String password;
    public static String rootpath;
 // Notice that this is  static  Decorate, facilitate sftputil Direct value 
    public static String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        SftpConfig.ip = ip;
    }
    public static Integer getPort() {
        return port;
    }
    public void setPort(Integer port) {
        SftpConfig.port = port;
    }
    public static String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        SftpConfig.username = username;
    }
    public static String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        SftpConfig.password = password;
    }
    public static String getRootpath() {
        return rootpath;
    }
    public void setRootpath(String rootpath) {
        SftpConfig.rootpath = rootpath;
    }
}

The following is a specific tool class, the code is relatively simple, you can download and optimize yourself under 1, and I have time to optimize


package com.uinnova.ftpsynweb.util;
import com.jcraft.jsch.*;
import com.uinnova.ftpsynweb.config.SftpConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;
import javax.transaction.SystemException;
import java.io.*;
import java.util.*;
/**
 * SFTP工具类
 */
@Slf4j
@Component
public class SftpUtil {
    @Autowired
    SftpConfig sftpConfig;
    private static String sftp_ip = SftpConfig.getIp();
    private static Integer sftp_port = SftpConfig.getPort();
    private static String sftp_username = SftpConfig.getUsername();
    private static String sftp_password = SftpConfig.getPassword();
    /**
     * sftp存储根目录
     */
    public static String windows_path = "D:SFTP/";
    public static String linux_path = "/home/xuyy/";
    private Session session;
    private ChannelSftp channel;
    /**
     * 规避多线程并发不断开问题
     */
    private volatile static ThreadLocal<SftpUtil> sftpLocal = new ThreadLocal<>();
    private SftpUtil() {
    }
    private SftpUtil(String host, Integer port, String username, String password) {
        super();
        init(host, port, username, password);
    }
    /**
     * 获取本地线程存储的sftp客户端,使用玩必须调用 release()释放连接
     *
     * @return
     * @throws Exception
     */
    public static SftpUtil getSftpUtil() {
        SftpUtil sftpUtil = sftpLocal.get();
        if (null == sftpUtil || !sftpUtil.isConnected()) {
            sftpLocal.set(new SftpUtil(sftp_ip, sftp_port, sftp_username, sftp_password));
        }
        return sftpLocal.get();
    }
    /**
     * 获取本地线程存储的sftp客户端,使用玩必须调用 release()释放连接
     *
     * @param host
     * @param port
     * @param username
     * @param password
     * @return
     */
    public static SftpUtil getSftpUtil(String host, Integer port, String username, String password) {
        SftpUtil sftpUtil = sftpLocal.get();
        if (null == sftpUtil || !sftpUtil.isConnected()) {
            log.info("建立连接");
            sftpLocal.set(new SftpUtil(host, port, username, password));
        } else {
            log.info("连接已经存在");
        }
        return sftpLocal.get();
    }
    /**
     * 初始化 创建1个新的 SFTP 通道
     *
     * @param host
     * @param port
     * @param username
     * @param password
     */
    private void init(String host, Integer port, String username, String password) {
        try {
            //场景JSch对象
            JSch jSch = new JSch();
            // jsch.addIdentity(); 私钥
            session = jSch.getSession(username, host, port);
            // 第1次登陆时候提示, (ask|yes|no)
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("compression.s2c", "zlib,none");
            config.put("compression.c2s", "zlib,none");
            session.setConfig(config);
            //设置超时
//            session.setTimeout(10*1000);
            //设置密码
            session.setPassword(password);
            session.connect();
            //打开SFTP通道
            channel = (ChannelSftp) session.openChannel("sftp");
            //建立SFTP通道的连接
            channel.connect();
            // 失败重试2次  失败不管了,只发送1次 失败回复  并行调用所有节点
        } catch (JSchException e) {
            log.error("init话sftp异常,可能是获得连接错误,请检查用户名密码或者重启sftp服务" + e);
        }
    }
    /**
     * 是否已连接
     *
     * @return
     */
    private boolean isConnected() {
        return null != channel && channel.isConnected();
    }
    /**
     * 关闭通道
     */
    public void closeChannel() {
        if (null != channel) {
            try {
                channel.disconnect();
            } catch (Exception e) {
                log.error("关闭SFTP通道发生异常:", e);
            }
        }
        if (null != session) {
            try {
                session.disconnect();
            } catch (Exception e) {
                log.error("SFTP关闭 session异常:", e);
            }
        }
    }
    /**
     * 每次连接必须释放资源,类似OSS服务
     * 释放本地线程存储的sftp客户端
     */
    public static void release() {
        if (null != sftpLocal.get()) {
            sftpLocal.get().closeChannel();
            sftpLocal.set(null);
        }
    }
    /**
     * 列出目录下文件,只列出文件名字,没有类型
     *
     * @param dir 目录
     * @return
     */
    public List list(String dir) {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "  " + sftp_password + "是否可以访问");
            return null;
        }
        Vector<ChannelSftp.LsEntry> files = null;
        try {
            files = channel.ls(dir);
        } catch (SftpException e) {
            log.error(e.getMessage());
        }
        if (null != files) {
            List fileNames = new ArrayList<String>();
            Iterator<ChannelSftp.LsEntry> iter = files.iterator();
            while (iter.hasNext()) {
                String fileName = iter.next().getFilename();
                if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
                    continue;
                }
                fileNames.add(fileName);
            }
            return fileNames;
        }
        return null;
    }
    /**
     * 列出文件详情
     *
     * @param dir
     * @return
     */
    public List listDetail(String dir) {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "  " + sftp_password + "是否可以访问");
            return null;
        }
        Vector<ChannelSftp.LsEntry> files = null;
        try {
            files = channel.ls(dir);
        } catch (SftpException e) {
            log.error("listDetail 获取目录列表 channel.ls " + dir + "失败 " + e);
        }
        if (null != files) {
            List<Map<String, String>> fileList = new ArrayList<>();
            Iterator<ChannelSftp.LsEntry> iter = files.iterator();
            while (iter.hasNext()) {
                ChannelSftp.LsEntry next = iter.next();
                Map<String, String> map = new HashMap<>();
                String fileName = next.getFilename();
                if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
                    continue;
                }
                String size = String.valueOf(next.getAttrs().getSize());
                long mtime = next.getAttrs().getMTime();
                String type = "";
                String longname = String.valueOf(next.getLongname());
                if (longname.startsWith("-")) {
                    type = "file";
                } else if (longname.startsWith("d")) {
                    type = "dir";
                }
                map.put("name", fileName);
                map.put("size", size);
                map.put("type", type);
                map.put("mtime", DateTimeUtil.timestampToDate(mtime));
                fileList.add(map);
            }
            return fileList;
        }
        return null;
    }
    /**
     * 递归获得文件path下所有文件列表
     *
     * @param path
     * @param list
     * @return
     * @throws SftpException
     */
    public List<String> listOfRecursion(String path, List<String> list) throws SftpException {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "" + sftp_password + "是否可以访问");
            return null;
        }
        Vector<ChannelSftp.LsEntry> files = null;
        files = channel.ls(path);
        for (ChannelSftp.LsEntry entry : files) {
            if (!entry.getAttrs().isDir()) {
                String str = path + "/" + entry.getFilename();
                str = str.replace("//", "/");
                list.add(str);
            } else {
                if (!entry.getFilename().equals(".") && !entry.getFilename().equals("..")) {
                    listOfRecursion(path + "/" + entry.getFilename(), list);
                }
            }
        }
        log.debug(list.toString());
        return list;
    }
    /**
     * @param file       上传文件
     * @param remotePath 服务器存放路径,支持多级目录
     * @throws SystemException
     */
    public void upload(File file, String remotePath) throws SystemException {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "" + sftp_password + "是否可以访问");
        }
        FileInputStream fileInputStream = null;
        try {
            if (file.isFile()) {
                String rpath = remotePath;//服务器要创建的目录
                try {
                    createDir(rpath);
                } catch (Exception e) {
                    throw new SystemException("创建路径失败:" + rpath);
                }
                channel.cd(remotePath);
                System.out.println(remotePath);
                fileInputStream = new FileInputStream(file);
                channel.put(fileInputStream, file.getName());
            }
        } catch (FileNotFoundException e) {
            throw new SystemException("上传文件没有找到");
        } catch (SftpException e) {
            throw new SystemException("上传ftp服务器错误");
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * @param file       上传文件
     * @param remoteName 上传文件名字
     * @param remotePath 服务器存放路径,支持多级目录
     * @throws SystemException
     */
    public boolean upload(File file, String remoteName, String remotePath) {
        if (channel == null) {
            System.out.println("get sftp connect fail,please reboot sftp client");
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "" + sftp_password + "是否可以访问");
        } else {
            FileInputStream fileInputStream = null;
            try {
                if (file.isFile()) {
                    //服务器要创建的目录
                    String rpath = remotePath;
                    createDir(rpath);
                    channel.cd(remotePath);
                    log.error(remotePath + "  " + remoteName);
                    fileInputStream = new FileInputStream(file);
                    channel.put(fileInputStream, remoteName);
                    return true;
                }
            } catch (FileNotFoundException e) {
                log.error("上传文件没有找到", e.getMessage());
                return false;
            } catch (SftpException e) {
                log.error("upload" + remotePath + e);
                return false;
            } finally {
                try {
                    if (fileInputStream != null) {
                        fileInputStream.close();//这里要关闭文件流
                    } else {
                        log.error("流不存在" + remotePath + "  " + remoteName);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // try to delete the file immediately
//                boolean deleted = false;
//                try {
//                    deleted = file.delete();
//                } catch (SecurityException e) {
//                    log.error(e.getMessage());
//                }
//                // else delete the file when the program ends
//                if (deleted) {
//                    System.out.println("Temp file deleted.");
//                    log.info("Temp file deleted.");
//                } else {
//                    file.deleteOnExit();
//                    System.out.println("Temp file scheduled for deletion.");
//                    log.info("Temp file scheduled for deletion.");
//                }
            }
        }
        return false;
    }
    public boolean upload(InputStream inputStream, String remoteName, String remotePath) {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "" + sftp_password + "是否可以访问");
        } else {
            try {
                //服务器要创建的目录
                String rpath = remotePath;
                createDir(rpath);
                channel.cd(remotePath);
                log.debug(remotePath + "  " + remoteName);
                channel.put(inputStream, remoteName);
                return true;
            } catch (SftpException e) {
                log.error("upload路径不存在" + remotePath + e);
                return false;
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();//这里要关闭文件流
                    } else {
                        log.error("流不存在" + remotePath + "  " + remoteName);
                    }
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
                // try to delete the file immediately
//                boolean deleted = false;
//                try {
//                    deleted = file.delete();
//                } catch (SecurityException e) {
//                    log.error(e.getMessage());
//                }
//                // else delete the file when the program ends
//                if (deleted) {
//                    System.out.println("Temp file deleted.");
//                    log.info("Temp file deleted.");
//                } else {
//                    file.deleteOnExit();
//                    System.out.println("Temp file scheduled for deletion.");
//                    log.info("Temp file scheduled for deletion.");
//                }
            }
        }
        return false;
    }
    /**
     * 下载文件
     *
     * @param rootDir
     * @param filePath
     * @return
     */
    public File downFile(String rootDir, String filePath) {
        if (channel == null) {
            log.error("获取sftp连接失败,请检查" + sftp_ip + +sftp_port + "@" + sftp_username + "  " + sftp_password + "是否可以访问");
            return null;
        }
        OutputStream outputStream = null;
        File file = null;
        try {
            channel.cd(rootDir);
            String folder = System.getProperty("java.io.tmpdir");
            file = new File(folder + File.separator + filePath.substring(filePath.lastIndexOf("/") + 1));
//            file = new File(filePath.substring(filePath.lastIndexOf("/") + 1));
            outputStream = new FileOutputStream(file);
            channel.get(filePath, outputStream);
        } catch (SftpException e) {
            log.error("downFile" + filePath + e);
            file = null;
        } catch (FileNotFoundException e) {
            log.error("FileNotFoundException", e);
            file = null;
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }
    /**
     * 创建1个文件目录
     */
    public void createDir(String createpath) {
        try {
            if (isDirExist(createpath)) {
                this.channel.cd(createpath);
                return;
            }
            String pathArry[] = createpath.split("/");
            StringBuffer filePath = new StringBuffer("/");
            for (String path : pathArry) {
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(filePath.toString())) {
                    channel.cd(filePath.toString());
                } else {
                    // 建立目录
                    channel.mkdir(filePath.toString());
                    // 进入并设置为当前目录
                    channel.cd(filePath.toString());
                }
            }
            this.channel.cd(createpath);
        } catch (SftpException e) {
            log.error("createDir" + createpath + e);
        }
    }
    /**
     * 判断目录是否存在
     */
    public boolean isDirExist(String directory) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = channel.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }
    static String PS = "/";
    /**
     * This method is called recursively to download the folder content from SFTP server
     *
     * @param sourcePath
     * @param destinationPath
     * @throws SftpException
     */
    public void recursiveFolderDownload(String sourcePath, String destinationPath) throws SftpException {
        Vector<ChannelSftp.LsEntry> fileAndFolderList = channel.ls(sourcePath); // Let list of folder content
        //Iterate through list of folder content
        for (ChannelSftp.LsEntry item : fileAndFolderList) {
            if (!item.getAttrs().isDir()) { // Check if it is a file (not a directory).
                if (!(new File(destinationPath + PS + item.getFilename())).exists()
                        || (item.getAttrs().getMTime() > Long
                        .valueOf(new File(destinationPath + PS + item.getFilename()).lastModified()
                                / (long) 1000)
                        .intValue())) { // Download only if changed later.
                    new File(destinationPath + PS + item.getFilename());
                    channel.get(sourcePath + PS + item.getFilename(),
                            destinationPath + PS + item.getFilename()); // Download file from source (source filename, destination filename).
                }
            } else if (!(".".equals(item.getFilename()) || "..".equals(item.getFilename()))) {
                new File(destinationPath + PS + item.getFilename()).mkdirs(); // Empty folder copy.
                recursiveFolderDownload(sourcePath + PS + item.getFilename(),
                        destinationPath + PS + item.getFilename()); // Enter found folder on server to read its contents and create locally.
            }
        }
    }
    /**
     * 文件夹不存在,创建
     *
     * @param folder 待创建的文件节夹
     */
    public void createFolder(String folder) {
        SftpATTRS stat = null;
        try {
            stat = channel.stat(folder);
        } catch (SftpException e) {
            log.error("复制目的地文件夹" + folder + "不存在,创建");
        }
        if (stat == null) {
            try {
                channel.mkdir(folder);
            } catch (SftpException e) {
                log.error("创建失败", e.getCause());
            }
        }
    }
    public InputStream get(String filePath) {
        InputStream inputStream = null;
        try {
            inputStream = channel.get(filePath);
        } catch (SftpException e) {
            log.error("get" + e);
        }
        return inputStream;
    }
    public void put(InputStream inputStream, String filePath) {
        try {
            channel.put(inputStream, filePath);
        } catch (SftpException e) {
            log.error("put" + e);
        }
    }
    public Vector<ChannelSftp.LsEntry> ls(String filePath) {
        Vector ls = null;
        try {
            ls = channel.ls(filePath);
        } catch (SftpException e) {
            log.error("ls" + e);
        }
        return ls;
    }
    /**
     * 复制文件夹
     *
     * @param src  源文件夹
     * @param desc 目的文件夹
     */
    public void copy(String src, String desc) {
//        检查目的文件存在与否,不存在则创建
        this.createDir(desc);
//        查看源文件列表
        Vector<ChannelSftp.LsEntry> fileAndFolderList = this.ls(src);
        for (ChannelSftp.LsEntry item : fileAndFolderList) {
            if (!item.getAttrs().isDir()) {//是1个文件
                try (InputStream tInputStream = this.get(src + PS + item.getFilename());
                     ByteArrayOutputStream baos = new ByteArrayOutputStream()
                ) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = tInputStream.read(buffer)) > -1) {
                        baos.write(buffer, 0, len);
                    }
                    baos.flush();
                    InputStream nInputStream = new ByteArrayInputStream(baos.toByteArray());
                    this.put(nInputStream, desc + PS + item.getFilename());
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
                // 排除. 和 ..
            } else if (!(".".equals(item.getFilename()) || "..".equals(item.getFilename()))) {
//                创建文件,可能不需要
                this.createFolder(desc + PS + item.getFilename());
                //递归复制文件
                copy(src + PS + item.getFilename(), desc + PS + item.getFilename());
            }
        }
    }
    /**
     * 删除指定目录文件
     *
     * @param filePath 删除文件路径
     * @return
     */
    public Boolean del(String filePath) {
        boolean flag = false;
        try {
            channel.rm(filePath);
            flag = true;
        } catch (SftpException e) {
            flag = false;
            log.error("删除文件错误报告: " + e);
        }
        return flag;
    }
}

The following are several specific interfaces, which are also posted here, which is convenient for everyone to use


@Slf4j
@RestController
public class FileController {
    /**
     * @param file        Upload a file 
     * @param targetPath  Save file path 
     * @param fileName    Upload file name 
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/file/upload")
    @ResponseBody
    public Return upload(@RequestParam("file") MultipartFile file, String targetPath, String fileName) throws IOException {
        log.debug(" Original name of upload file: " + file.getOriginalFilename() + " Upload path: " + targetPath + " Upload file name:  " + fileName);
        InputStream uploadFile = file.getInputStream();
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        boolean upload = false;
        if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
            upload = sftpUtil.upload(uploadFile, fileName, targetPath);
        } else {
            upload = sftpUtil.upload(uploadFile, fileName, SftpConfig.getRootpath() + targetPath);
        }
        SftpUtil.release();
        return Return.Ok(upload);
    }
    /**
     *  The specific path of the file to be downloaded 
     *
     * @param targetPath
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = "/file/download")
    @ResponseBody
    public void download(String targetPath, HttpServletResponse response) throws UnsupportedEncodingException {
        log.debug(" Download file name " + targetPath);
//        targetPath = new String(targetPath.getBytes("ISO8859-1"), "UTF-8");
        if (StringUtils.isEmpty(targetPath) || !targetPath.contains("/")) {
            log.error(" The download path is incorrect " + targetPath);
//            return Return.Fail(" The download path is incorrect ");
        }
        String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1);
        log.debug(fileName);
        File file = null;
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
            file = sftpUtil.downFile("/", targetPath);
        } else {
            file = sftpUtil.downFile("/", SftpConfig.getRootpath() + targetPath);
        }
        SftpUtil.release();
        if (!Objects.isNull(file)) {
            //  Configuration file download 
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            //  The downloaded file can display Chinese normally 
//            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1"));
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
//                return Return.Ok(" Download succeeded ");
            } catch (Exception e) {
                log.error("down fail" + e);
//                return Return.Fail(" Lower lost ");
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        log.error("down fail" + e);
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        log.error("down fail" + e);
                    }
                }
            }
        }
//        return Return.Fail(" Lower lost ");
    }
    /**
     *  Get sftp The following file message list 
     *
     * @param filePath  File path 
     * @return
     */
    @RequestMapping(value = "/file/list")
    @ResponseBody
    public Return list(@RequestParam("filePath") String filePath) {
        log.debug(" Get the list below the path   : {}", filePath);
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        List<String> list = new ArrayList();
        if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
            list = sftpUtil.listDetail(filePath);
        } else {
            list = sftpUtil.listDetail(SftpConfig.getRootpath() + filePath);
        }
        SftpUtil.release();
        return Return.Ok(list);
    }
    /**
     *  Recursive retrieval of files path List of all files below 
     *
     * @param filePath  File path 
     * @return
     */
    @RequestMapping(value = "/file/listOfRecursion")
    @ResponseBody
    public Return listOfRecursion(@RequestParam("filePath") String filePath) {
        log.debug(" Get the list below the path   : {}", filePath);
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        ArrayList<String> strings = new ArrayList<>();
        Return ret = null;
        List<String> list;
        List<String> list1 = new ArrayList<>();
        try {
            if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
                list = sftpUtil.listOfRecursion(filePath, strings);
                ret = Return.Ok(list);
            } else {
                list = sftpUtil.listOfRecursion(SftpConfig.getRootpath() + filePath, strings);
                for (String str : list) {
                    str = StringUtils.substring(str, SftpConfig.getRootpath().length() - 1);
                    list1.add(str);
                }
                ret = Return.Ok(list1);
            }
        } catch (SftpException e) {
            log.error("listOfRecursion  Get directory list  channel.ls " + filePath + " Failure  " + e);
            SftpUtil.release();
            ret = Return.Fail(e.getMessage());
        }finally {
            SftpUtil.release();
        }
        return ret;
    }
    /**
     * sftp Internal replication folder 
     *
     * @param src   Source folder 
     * @param desc  Destination folder 
     * @return
     */
    @RequestMapping(value = "file/copy")
    @ResponseBody
    public Return copy(String src, String desc) {
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
            sftpUtil.copy(src, desc);
        } else {
            sftpUtil.copy(SftpConfig.getRootpath() + src, SftpConfig.getRootpath() + desc);
        }
        SftpUtil.release();
        return Return.Ok(" Successful replication ");
    }
    /**
     *  Delete a file   File Existence Returns true  File does not exist or deletion fails to return  false
     *
     * @param filePath
     * @return
     */
    @RequestMapping(value = "file/del")
    @ResponseBody
    public Return del(String filePath) {
        log.debug(" Delete this file   : {}", filePath);
        Boolean flag = false;
        SftpUtil sftpUtil = SftpUtil.getSftpUtil();
        if (SftpConfig.WIN.equals(SftpConfig.getEnv())) {
            flag = sftpUtil.del(filePath);
        } else {
            flag = sftpUtil.del(SftpConfig.getRootpath() + filePath);
        }
        SftpUtil.release();
        return new Return(flag, flag ? " Delete succeeded " : " File does not exist or deletion failed ");
    }   
}

Related articles: