springboot如何读取sftp的文件

目录
  • springboot读取sftp的文件
    • 1.添加pom依赖(基于springboot项目)
    • 2.application.yaml配置文件
    • 3.工具类
    • 4.实际调用
  • springboot使用SFTP文件上传

springboot读取sftp的文件

1.添加pom依赖(基于springboot项目)

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

2.application.yaml配置文件

sftp:
   ip: 192.168.1.102
   port: 22
   username: admin
   password: admin
   root: /img #文件根目录

3.工具类

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 {

    /**
     * 下载重试次数
     */
    private static final int DOWNLOAD_RETRY = 3;

    /**
     * 下载重试间隔时间 单位毫秒
     */
    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;
    }

    /**
     * 获取SFTP连接
     *
     * @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();
                // 设置第一次登陆的时候主机公钥确认提示,可选值:(ask | yes | no)
                config.put("StrictHostKeyChecking", "no");
                session.setConfig(config);
                session.connect();
                //sftp协议
                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;
    }

    /**
     *
     * 关闭连接 server
     */
    public static void close() {
        if (client != null && client.isConnected()) {
            client.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
    /**
     * 单次下载文件
     *
     * @param downloadFile 下载文件地址
     * @param saveFile     保存文件地址
     * @param ip           主机地址
     * @param port         主机端口
     * @param username     用户名
     * @param password     密码
     * @param rootPath     根目录
     * @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) {
            //获取连接
            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;
    }
    /**
     * 下载文件
     *
     * @param downloadFile 下载文件的路径
     * @param saveFile     保存的路径
     * @param rootPath     根目录
     * @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 {
                //获取连接、读取文件(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.实际调用

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使用SFTP文件上传

最近在工作功能使用了sftp做文件上传下载的功能,在这里简单的记录一下

pom文件中引入相关的jar包

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

建立springboot项目,在application.properties添加如下配置

sftp.ip=127.0.0.1
sftp.port=22
sftp.username=xuyy
sftp.password=paswpord
#ftp根目录
sftp.rootpath="D:SFTP/

上面一sftp开头的都是自定义配置,需要写个配置类读取一下,自动注入到springboot中

package com.uinnova.ftpsynweb.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * 特点: 读取配置文件。可以对静态变量直接赋值
 *
 * @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;
 //注意这里是 static 修饰,便于sftputil直接取值
    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;
    }
}

下面是具体的工具类,代码写的比较简单,可以自己下载优化一下,等我有时间在优化

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();
    }
    /**
     * 初始化 创建一个新的 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);
            // 第一次登陆时候提示, (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次  失败不管了,只发送一次 失败回复  并行调用所有节点
        } 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;
    }
    /**
     * 创建一个文件目录
     */
    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()) {//是一个文件
                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;
    }
}

下面是具体的几个接口,这里也贴出来了,方便大家使用

@Slf4j
@RestController
public class FileController {
    /**
     * @param file       上传文件
     * @param targetPath 保存文件路径
     * @param fileName   上传文件名字
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/file/upload")
    @ResponseBody
    public Return upload(@RequestParam("file") MultipartFile file, String targetPath, String fileName) throws IOException {
        log.debug("上传文件原始名字:" + file.getOriginalFilename() + "上传路径:" + targetPath + "上传文件名: " + 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);
    }
    /**
     * 需要下载的文件具体路径
     *
     * @param targetPath
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = "/file/download")
    @ResponseBody
    public void download(String targetPath, HttpServletResponse response) throws UnsupportedEncodingException {
        log.debug("下载文件名字" + targetPath);
//        targetPath = new String(targetPath.getBytes("ISO8859-1"), "UTF-8");
        if (StringUtils.isEmpty(targetPath) || !targetPath.contains("/")) {
            log.error("下载路径不正确" + targetPath);
//            return Return.Fail("下载路径不正确");
        }
        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)) {
            // 配置文件下载
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
//            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("下载成功");
            } catch (Exception e) {
                log.error("down fail" + e);
//                return Return.Fail("下載失敗");
            } 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("下載失敗");
    }
    /**
     * 获取sftp下文件消息列表
     *
     * @param filePath 文件路径
     * @return
     */
    @RequestMapping(value = "/file/list")
    @ResponseBody
    public Return list(@RequestParam("filePath") String filePath) {
        log.debug("获取路径下列表 :{}", 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);
    }
    /**
     * 递归获得文件path下所有文件列表
     *
     * @param filePath 文件路径
     * @return
     */
    @RequestMapping(value = "/file/listOfRecursion")
    @ResponseBody
    public Return listOfRecursion(@RequestParam("filePath") String filePath) {
        log.debug("获取路径下列表 :{}", 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 获取目录列表 channel.ls " + filePath + "失败 " + e);
            SftpUtil.release();
            ret = Return.Fail(e.getMessage());
        }finally {
            SftpUtil.release();
        }
        return ret;
    }
    /**
     * sftp内复制文件夹
     *
     * @param src  源文件夹
     * @param desc 目的文件夹
     * @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("复制成功");
    }
    /**
     * 删除文件 文件存在返回true ,文件不存在或删除失败返回 false
     *
     * @param filePath
     * @return
     */
    @RequestMapping(value = "file/del")
    @ResponseBody
    public Return del(String filePath) {
        log.debug("删除此文件 :{}", 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 ? "删除成功" : "文件不存在或删除失败");
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决SpringBoot文件上传临时目录找不到的问题

    SpringBoot文件上传临时目录问题 我相信大家在把项目部署到服务器上面时候都会遇到这样一个问题: org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request;nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.133776721859504205

  • springboot2.1.3配置sftp自定义sftp连接池的详细过程

    项目地址 项目地址:https://gitee.com/xuelingkang/spring-boot-demo 完整配置参考com.example.ftp包 maven: <!-- sftp --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </de

  • springboot以FTP方式上传文件到远程服务器

    一.html代码   <div class="layui-form-item"> <label class="layui-form-label">上传附件:</label> <div class="layui-input-block doc-litpic"> <button type="button" name="avatar" class="

  • springboot如何读取sftp的文件

    目录 springboot读取sftp的文件 1.添加pom依赖(基于springboot项目) 2.application.yaml配置文件 3.工具类 4.实际调用 springboot使用SFTP文件上传 springboot读取sftp的文件 1.添加pom依赖(基于springboot项目) <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId>

  • springboot如何读取application.yml文件

    现在开发主要使用微服务框架springboot,在springboot中经常遇到读取application.yml文件的情形. 一.概述 开发过程中经常遇到要读取application.yml文件中的属性值,本文总结几种读取的方式,供参考. 二.详述 我这里使用的是springboot-2.1.2.RELEASE版本,这里使用的是application.properties的配置方式,和使用application.yml的方式是一样的.下面是application.properties文件的内容

  • 解决SpringBoot jar包中的文件读取问题实现

    前言 SpringBoot微服务已成为业界主流,从开发到部署都非常省时省力,但是最近小明开发时遇到一个问题:在代码中读取资源文件(比如word文档.导出模版等),本地开发时可以正常读取 ,但是,当我们打成jar包发布到服务器后,再次执行程序时就会抛出找不到文件的异常. 背景 这个问题是在一次使用freemarker模版引擎导出word报告时发现的.大概说一下docx导出java实现思路:导出word的文档格式为docx,事先准备好一个排好版的docx文档作为模版,读取解析该模版,将其中的静态资源

  • java(包括springboot)读取resources下文件方式实现

    本文主要介绍了java(包括springboot)读取resources下文件方式实现,分享给大家,具体如下: 1.使用项目内路径读取,该路径只在开发工具中显示,类似:src/main/resources/resource.properties.只能在开发工具中使用,部署之后无法读取.(不通用) File file = new File("src/main/resources/resource.properties"); @Test public void testReadFile2(

  • Springboot 项目读取Resources目录下的文件(推荐)

    需求描述:企业开发过程中,经常需要将一些静态文本数据放到Resources目录下,项目启动时或者程序运行中,需要读取这些文件. 读取Resources目录下文件的方法 /** * @Description: 读取resources 目录下的文件 * @Author: ljj * @CreateDate: 2020/11/3 17:20 * @UpdateUser: * @UpdateDate: * @UpdateReakem * @param filePath * @Return: java.l

  • SpringBoot 如何读取classpath下的文件

    SpringBoot 读取classpath下文件 开发过程中,必不可少的需要读取文件,对于打包方式的不同,还会存在一些坑,比如以jar包方式部署时,文件都存在于jar包中,某些读取方式在开发工程中都可行,但是打包后,由于文件被保存在jar中,会导致读取失败. 这时就需要通过类加载器读取文件,类加载器可以读取jar包中的class类当然也可以读取jar包中的文件. // 方法1:获取文件或流 this.getClass().getResource("/")+fileName; this

  • SpringBoot读取Resource下文件的4种方法

    SpringBoot读取Resource下文件 最近在项目中涉及到Excle的导入功能,通常是我们定义完模板供用户下载,用户按照模板填写完后上传:这里待下载模板位置为resource/excelTemplate/test.xlsx,尝试了四种读取方式,并且测试了四种读取方式分别的windows开发环境下(IDE中)读取和生产环境(linux下jar包运行读取). 第一种: ClassPathResource classPathResource = new ClassPathResource("e

  • SpringBoot不读取bootstrap.yml/properties文件问题

    目录 今天写创建了一个SpringBoot项目,配置文件从其他项目拷贝了一份bootstrap.yml 之前一直用的application.yml 心想:application.yml 优先级没有bootstrap.yml 高,bootstrap配置文件肯定没问题 项目一跑来,发现配置文件里面的内容没读取到. 之后通过各种查资料,才明白了application.yml 和bootstrap.yml 的区别,不仅仅是优先级的问题. 先说我的问题是什么原因吧: SpringBoot 项目中如果没有依

  • springboot读取resources下文件的方式详解

    项目中很多时候需要读取自定义配置文件,本地开发工具怎么写都成功但是部署到服务其上就出现问题, 异常BOOT-INF/classes!/config.xml (文件名.目录名或卷标语法不正确.)路径中带有叹号之类的 了解了大概之后就是springboot打成jar是一个文件,也就是一个压缩包,没有办法读取压缩文件里的路径,因此要解决这个问题了解读取配置文件的原理,直接获取文件流就可以了. 1.使用项目内路径读取,只能在开发工具中使用,部署之后无法读取.(不通用) 类似:src/main/resou

  • springboot读取application.yaml文件数据的方法

    本文实例为大家分享了springboot读取application.yaml文件数据的具体代码,供大家参考,具体内容如下 提示:以下是本篇文章正文内容,下面案例可供参考 一.创建并编辑对应的文件 1.application.yaml !!!这里一定要注意,datasource一定不能写成dataSource,因为会和Spring内部的产生冲突 server:   port: 8080 contry: china user:   - name: zhangsan     age: 18   - n

随机推荐