Java SFTP 上傳、下載等操作

編碼語言Codelang發表於2020-10-31

Java SFTP 上傳、下載等操作

實際開發中用到了 SFTP 用於交換批量資料檔案,然後琢磨了下這方面的東西,基於 JSch 寫了個工具類記錄下,便於日後使用。

JSchSSH2 的純Java實現。JSch 可以連線到sshd伺服器並使用埠轉發,X11轉發,檔案傳輸等,並且很方便的將其功能整合到Java程式中。

1、新增依賴

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

2、SFTPUtils 工具類

public class SFTPUtils {
    private Logger log = LoggerFactory.getLogger(SFTPUtils.class);

    private String host; // 主機名稱/IP
    private int port = 22; // 埠
    private String username; // 使用者名稱
    private String password; // 密碼

    private ChannelSftp sftp = null;
    private Channel channel = null;
    private Session session = null;

    public SFTPUtils(String host, String userName, String password) {
        this.host = host;
        this.username = userName;
        this.password = password;
    }

    public SFTPUtils(String host, int port, String userName, String password) {
        this.host = host;
        this.port = port;
        this.username = userName;
        this.password = password;
    }

    /**
     * 連線SFTP伺服器
     *
     * @throws JSchException
     */
    public void connect() throws JSchException {
        JSch jSch = new JSch();
        session = jSch.getSession(username, host, port);
        session.setPassword(password);
        session.setConfig(this.buildConfig());
        session.connect();
        channel = session.openChannel("sftp");
        channel.connect();
        sftp = (ChannelSftp) channel;
        log.info("連線主機:{} 登入成功", host);
    }

    /**
     * 構建連線配置引數
     *
     * @return Properties
     */
    private Properties buildConfig() {
        Properties properties = new Properties();
        properties.put("StrictHostKeyChecking", "no");
        return properties;
    }

    /**
     * 關閉連線
     */
    public void disconnect() {
        try {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
            if (channel.isConnected()) {
                channel.disconnect();
            }
            if (session.isConnected()) {
                session.disconnect();
            }
        } catch (Throwable e) {
            //ignore
        }
    }

    /**
     * 下載檔案
     *
     * @param sftpPath   伺服器路徑,不指定路徑預設是FTP的根路徑,指定路徑是指的SFTP的根路徑下開始。
     *                   例如:SFTP根路徑為:/sftp/file,那麼預設下載檔案會去根路徑下載,而指定 sftpPath 也是從根路徑下開始;
     *                   指定 sftpPath 為 word,那麼是從 /sftp/file/word 路徑中查詢檔案下載。為空表示忽略該引數。
     * @param fileName   檔名
     * @param toFilePath 下載儲存檔案路徑,路徑+檔名,例如:d:/test.txt
     * @return
     */
    public boolean downloadFile(String sftpPath, String fileName, String toFilePath) {
        FileOutputStream fileOutputStream = null;
        try {
            if (StringUtils.isNotBlank(sftpPath)) {
                sftp.cd(sftpPath);
            }
            fileOutputStream = new FileOutputStream(new File(toFilePath));
            sftp.get(fileName, fileOutputStream);
            return true;
        } catch (Exception e) {
            log.error("下載檔案錯誤", e);
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    //ignore
                }
            }
        }
        return false;
    }

    /**
     * 上傳檔案
     *
     * @param sftpPath      伺服器路徑,不指定路徑預設是FTP的根路徑,指定路徑是指的SFTP的根路徑下開始。
     *                      例如:SFTP根路徑為:/sftp/file,那麼預設下載檔案會去根路徑下載,而指定 sftpPath 也是從根路徑下開始;
     *                      指定 sftpPath 為 word,那麼是從 /sftp/file/word 路徑中查詢檔案下載。為空表示忽略該引數。
     * @param fileName      上傳後檔名
     * @param localFilePath 檔案路徑,路徑+檔名,例如:d:/test.txt
     * @return
     */
    public boolean uploadFile(String sftpPath, String fileName, String localFilePath) {
        FileInputStream inputStream = null;
        try {
            if (StringUtils.isNotBlank(sftpPath)) {
                sftp.cd(sftpPath);
            }
            inputStream = new FileInputStream(new File(localFilePath));
            sftp.put(inputStream, fileName);
            return true;
        } catch (Exception e) {
            log.error("上傳檔案錯誤", e);
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    //ignore
                }
            }
        }
        return false;
    }

    /**
     * 上傳檔案
     *
     * @param sftpPath    伺服器路徑,不指定路徑預設是FTP的根路徑,指定路徑是指的SFTP的根路徑下開始。
     *                    例如:SFTP根路徑為:/sftp/file,那麼預設下載檔案會去根路徑下載,而指定 sftpPath 也是從根路徑下開始;
     *                    指定 sftpPath 為 word,那麼是從 /sftp/file/word 路徑中查詢檔案下載。為空表示忽略該引數。
     * @param fileName    上傳後檔名
     * @param inputStream 檔案輸入流
     * @return
     */
    public boolean uploadFile(String sftpPath, String fileName, InputStream inputStream) {
        try {
            if (StringUtils.isNotBlank(sftpPath)) {
                sftp.cd(sftpPath);
            }
            sftp.put(inputStream, fileName);
            return true;
        } catch (Exception e) {
            log.error("上傳檔案錯誤", e);
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    //ignore
                }
            }
        }
        return false;
    }

    /**
     * 刪除檔案
     *
     * @param sftpPath 伺服器路徑,不指定路徑預設是FTP的根路徑,指定路徑是指的SFTP的根路徑下開始。
     *                 例如:SFTP根路徑為:/sftp/file,那麼預設下載檔案會去根路徑下載,而指定 sftpPath 也是從根路徑下開始;
     *                 指定 sftpPath 為 word,那麼是從 /sftp/file/word 路徑中查詢檔案下載。為空表示忽略該引數。
     * @param fileName 檔名
     * @return
     */
    public boolean deleteFile(String sftpPath, String fileName) {
        try {
            if (StringUtils.isNotBlank(sftpPath)) {
                sftp.cd(sftpPath);
            }
            sftp.rm(fileName);
            return true;
        } catch (Exception e) {
            log.error("刪除檔案失敗", e);
        }
        return false;
    }

    /**
     * 查詢指定目錄下資訊
     *
     * @param sftpPath 伺服器路徑,不指定路徑預設是FTP的根路徑,指定路徑是指的SFTP的根路徑下開始。
     *                 例如:SFTP根路徑為:/sftp/file,那麼預設下載檔案會去根路徑下載,而指定 sftpPath 也是從根路徑下開始;
     *                 指定 sftpPath 為 word,那麼是從 /sftp/file/word 路徑中查詢檔案下載。為空表示忽略該引數。
     * @return
     */
    public List<String> listFiles(String sftpPath) throws SftpException {
        Vector files = sftp.ls(sftpPath);
        List<String> result = new ArrayList<String>();
        Iterator iterator = files.iterator();
        while (iterator.hasNext()) {
            LsEntry isEntity = (LsEntry) iterator.next();
            result.add(isEntity.getFilename());
        }
        return result;
    }
}

在使用的的時候,需要呼叫 connect()開啟連線,使用完後呼叫 disconnect() 關閉連線 。

jsch 官方的文件說明 http://www.jcraft.com/jsch/

本文主要用於個人記錄筆記!

相關文章