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

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