Java 实现SFTP

1、pom.xml

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

2、配置文件

sftp:
  ftp_address: ${back.address}
  ftp_port: ${back.port}
  ftp_username: ${back.username}
  ftp_password: ${back.password}

3、工具类

import com.jcraft.jsch.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
import java.util.Vector;

@Slf4j
@Component
@Data
public class SFTPUtil {


    private Session session = null;
    private ChannelSftp channel = null;
    private int timeout = 60000;

    /**
     * 将CST时间类型字符串进行格式化输出
     *
     * @param str
     * @return
     */
    public static String CSTFormat(String str) {
        SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
        Date date = null;
        try {
            date = (Date) formatter.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }

    /**
     * 连接sftp服务器
     *
     * @throws JSchException
     */
    public void connect(String ftpUsername,String ftpAddress,int ftpPort,String ftpPassword) throws JSchException {
        if (channel != null) {
            System.out.println("channel is not null");
        }
        //创建JSch对象
        JSch jSch = new JSch();
        //根据用户名,主机ip和端口获取一个Session对象
        session = jSch.getSession(ftpUsername, ftpAddress, ftpPort);
        //设置密码
        session.setPassword(ftpPassword);
        System.out.println("Session created.");
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        //为Session对象设置properties
        session.setConfig(config);
        //设置超时
        session.setTimeout(timeout);
        //通过Session建立连接
        session.connect();
        System.out.println("Session connected.");
        // 打开SFTP通道
        channel = (ChannelSftp) session.openChannel("sftp");
        // 建立SFTP通道的连接
        channel.connect();
        System.out.println("Opening Channel.");
    }

    /**
     * 下载文件
     *
     * @param src linux服务器文件地址
     * @param dst 本地存放地址
     * @throws JSchException
     * @throws SftpException
     */
    public void download(String src, FileOutputStream dst) throws SftpException {
        channel.get(src, dst);
        channel.quit();
    }

    /**
     * 文件上传
     *
     * @param src 本地文件名
     * @param dst 目标文件名,若dst为目录,则目标文件名将与src文件名相同。
     *            采用默认的传输模式:OVERWRITE
     * @throws JSchException
     * @throws SftpException
     */

    public void upLoadPath(String src, String dst) throws SftpException {
        createDir(dst);
        channel.put(src, dst);
        channel.quit();
    }

    /**
     * 文件上传
     *
     * @param src      本地的input stream对象
     * @param dst      目标文件路径
     * @param fileName 目标文件名
     *                 采用默认的传输模式:OVERWRITE
     * @throws JSchException
     * @throws SftpException
     */
    public void upLoadFile(InputStream src, String dst, String fileName) throws SftpException {
        createDir(dst);
        channel.put(src, fileName);
        channel.quit();
    }
    /**
     * 文件删除
     */
    public void deleteFile(String directory,String deleteFile) throws SftpException {
        try {
            channel.cd(directory);
        } catch (SftpException e) {
            e.printStackTrace();
        }
        try {
            channel.rm(deleteFile);
        } catch (SftpException e) {
            e.printStackTrace();
        }
        channel.quit();
    }
    /**
     * 创建一个文件目录
     */
    public void createDir(String createPath) throws SftpException {

        if (isDirExist(createPath)) {
            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());
            }
        }
        channel.cd(createPath);
    }

    /**
     * 判断目录是否存在
     */
    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;
    }

    /**
     * 重命名指定文件或目录
     *
     * @param oldPath
     * @param newPath
     * @throws SftpException
     */
    public void rename(String oldPath, String newPath) throws SftpException {
        channel.rename(oldPath, newPath);
    }

    /**
     * 列出指定目录下的所有文件和子目录。
     *
     * @param path
     * @return
     * @throws SftpException
     */
    public Vector ls(String path) throws SftpException {
        Vector vector = channel.ls(path);
        return vector;
    }

    /**
     * 关闭连接
     */
    public void close() {
        //操作完毕后,关闭通道并退出本次会话
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }

        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
}

tips:
JSch有三种文件传输模式:
(1)OVERWRITE:完全覆盖模式。JSch的默认文件传输模式,传输的文件将覆盖目标文件。
(2)APPEND:追加模式。如果目标文件已存在,则在目标文件后追加。
(3)RESUME:恢复模式。如果文件正在传输时,由于网络等原因导致传输中断,则下一次传输相同的文件
时,会从上一次中断的地方续传。

4、使用

    //ftp服务器ip地址
    @Value("${sftp.ftp_address}")
    private String ftpAddress;
    //端口号
    @Value("${sftp.ftp_port}")
    private int ftpPort;
    //用户名
    @Value("${sftp.ftp_username}")
    private String ftpUsername;
    //密码
    @Value("${sftp.ftp_password}")
    private String ftpPassword;

    /**
     * 文件上传
     *
     * @param inputStream
     * @param path
     * @param fileName
     * @return
     */
    @Override
    public Map uploadFile(InputStream inputStream, String path, String fileName) {
        Map map = new HashMap();
        Boolean flog = false;
        String msg="";
        SFTPUtil sftpUtil = null;
        try {
            if(path.startsWith("/")){
                sftpUtil = new SFTPUtil();
                sftpUtil.connect(ftpUsername, ftpAddress, ftpPort, ftpPassword);
                sftpUtil.upLoadFile(inputStream, path, fileName);
                flog = true;
                msg = "文件上传成功";
            }else {
                log.error("上传路径必须以/开头");
                msg = "上传路径必须以/开头";
            }
        } catch (JSchException e) {
            log.error("连接sftp服务器失败:", e);
            msg = "连接服务器失败";
            e.printStackTrace();
        } catch (Exception e) {
            log.error("文件上传失败:", e);
            msg = "文件上传失败";
            e.printStackTrace();
        } finally {
            if (sftpUtil != null) {
                sftpUtil.close();
            }
        }
        map.put("flog", flog);
        map.put("msg", msg);
        return map;
    }

    /**
     * 获取指定目录下的文件列表
     *
     * @param path
     * @return
     */
    @Override
    public Map lsPath(String path) {
        Map map = new HashMap();
        Boolean flog = false;
        String msg="";
        SFTPUtil sftpUtil = null;
        try {
            sftpUtil = new SFTPUtil();
            sftpUtil.connect(ftpUsername, ftpAddress, ftpPort, ftpPassword);
            Vector vector = sftpUtil.ls(path);
            flog = true;
            map.put("flog", flog);
            map.put("list", vector);
            return map;
        } catch (JSchException e) {
            log.error("连接服务器失败:", e);
            msg = e.getMessage();
            e.printStackTrace();
        } catch (Exception e) {
            log.error("获取指定目录下的文件列表失败:", e);
            msg = "获取文件列表失败";
            e.printStackTrace();
        } finally {
            sftpUtil.close();
        }
        map.put("flog", flog);
        map.put("msg", msg);
        return map;
    }

    /**
     * 重命名指定文件
     *
     * @param oldPath
     * @param newPath
     * @return
     */
    @Override
    public Map renameFile(String oldPath, String newPath) {
        Map map = new HashMap();
        Boolean flog = false;
        String msg="";
        SFTPUtil sftpUtil = null;
        try {
            sftpUtil = new SFTPUtil();
            sftpUtil.connect(ftpUsername, ftpAddress, ftpPort, ftpPassword);
            sftpUtil.rename(oldPath, newPath);
            flog = true;
            msg = "重命名指定文件成功";
        } catch (JSchException e) {
            log.error("连接服务器失败:", e);
            msg = "连接服务器失败";
            e.printStackTrace();
        } catch (Exception e) {
            log.error("重命名指定文件失败:", e);
            msg = "重命名文件失败";
            e.printStackTrace();
        } finally {
            sftpUtil.close();
        }
        map.put("flog", flog);
        map.put("msg", msg);
        return map;

    }
    /**
     * 删除指定文件
     *
     * @param remotePath
     * @param remoteFileName
     * @return
     */
    @Override
    public void deleteFile(String remotePath, String remoteFileName){
        SFTPUtil sftpUtil = null;
        try {
            sftpUtil = new SFTPUtil();
            sftpUtil.connect(ftpUsername, ftpAddress, ftpPort, ftpPassword);
            sftpUtil.deleteFile(remotePath, remoteFileName);
        } catch (JSchException e) {
            log.error("连接sftp服务器失败:", e);
            e.printStackTrace();
        }catch (Exception e){
            log.error("文件删除异常:", e);
            e.printStackTrace();
        }
        finally {
            sftpUtil.close();
        }
    }

参考:https://blog.csdn.net/zhichao_qzc/article/details/80301994

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章