java實(shí)現(xiàn)SFTP服務(wù)器上傳下載

import com.google.common.base.Strings;
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.SftpATTRS;
import com.jcraft.jsch.SftpException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Vector;

/**
 * @Description: SFTP客戶端
 * @author gaoxiang
 * @date 2019年2月22日 下午4:31:03
 */
public class SftpClient {
    
    private final static Logger logger = LoggerFactory.getLogger(SftpClient.class);
    
    private static String host = "ip地址";
    
    private static String username = "用戶名";
    
    private static String password = "密碼";
    
    protected static String privateKey;// 密鑰文件路徑
    
    protected static String passphrase;// 密鑰口令
    
    private static int port = 22;
    
    private static ChannelSftp sftp = null;
    
    private static Session sshSession = null;
    
    public SftpClient(String host, String username, String password) {
        this.host = host;
        this.username = username;
        this.password = password;
    }
    
    public SftpClient(String host, String username, String password, int port) {
        this.host = host;
        this.username = username;
        this.password = password;
        this.port = port;
    }
    
    public SftpClient(String host, String username, String password, int port, String privateKey, String passphrase) {
        this.host = host;
        this.username = username;
        this.password = password;
        this.privateKey = privateKey;
        this.passphrase = passphrase;
        this.port = port;
    }
    
    public static void connect() {
        JSch jsch = new JSch();
        Channel channel = null;
        try {
            if (!StringUtils.isEmpty(privateKey)) {
                // 使用密鑰驗(yàn)證方式,密鑰可以使有口令的密鑰,也可以是沒(méi)有口令的密鑰
                if (!StringUtils.isEmpty(passphrase)) {
                    jsch.addIdentity(privateKey, passphrase);
                } else {
                    jsch.addIdentity(privateKey);
                }
            }
            sshSession = jsch.getSession(username, host, port);
            if (!StringUtils.isEmpty(password)) {
                sshSession.setPassword(password);
            }
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");// do not verify host
                                                            // key
            sshSession.setConfig(sshConfig);
            // session.setTimeout(timeout);
            // session.setServerAliveInterval(92000);
            sshSession.connect();
            // 參數(shù)sftp指明要打開(kāi)的連接是sftp連接
            channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            logger.error("連接【" + host + ":" + port + "】異常", e);
        }
    }
    
    /**
     * 獲取連接
     * @return channel
     */
    public void connectWithException() throws Exception {
        JSch jsch = new JSch();
        Channel channel = null;
        try {
            if (!StringUtils.isEmpty(privateKey)) {
                // 使用密鑰驗(yàn)證方式咐旧,密鑰可以使有口令的密鑰屋谭,也可以是沒(méi)有口令的密鑰
                if (!StringUtils.isEmpty(passphrase)) {
                    jsch.addIdentity(privateKey, passphrase);
                } else {
                    jsch.addIdentity(privateKey);
                }
            }
            sshSession = jsch.getSession(username, host, port);
            if (!StringUtils.isEmpty(password)) {
                sshSession.setPassword(password);
            }
            Properties sshConfig = new Properties();
            // do not verify host key
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            // session.setTimeout(timeout);
            // session.setServerAliveInterval(92000);
            sshSession.connect();
            // 參數(shù)sftp指明要打開(kāi)的連接是sftp連接
            channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            logger.error("連接【" + host + ":" + port + "】異常", e);
            throw new Exception("Could not connect to :" + host + ":" + port);
        }
    }
    
    /**
     * 關(guān)閉資源
     */
    public static void disconnect() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (sshSession != null) {
            if (sshSession.isConnected()) {
                sshSession.disconnect();
            }
        }
    }
    
    /**
     * sftp is connected
     *
     * @return
     */
    public static boolean isConnected() {
        return sftp != null && sftp.isConnected();
    }
    
    public InputStream downFile(String remotePath, String remoteFile) throws Exception {
        try {
            if (sftp == null)
                connect();
            sftp.cd(remotePath);
            return sftp.get(remoteFile);
        } catch (SftpException e) {
            logger.error("文件下載失敗或文件不存在赠摇!", e);
            throw e;
        } finally {
            // disconnect();
        }
    }
    
    public byte[] downLoad(String remotePath, String remoteFile) throws Exception {
        try {
            if (sftp == null)
                connect();
            sftp.cd(remotePath);
            InputStream input = sftp.get(remoteFile);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[10485760];
            int n = 0;
            while (-1 != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            }
            return output.toByteArray();
        } catch (SftpException e) {
            logger.error("文件下載失敗或文件不存在爷辙!", e);
        } finally {
            disconnect();
        }
        return null;
    }

    public static void main(String[] args){
        downloadFile("/home/apollo/QDAMC01/receive/20180926/20","loan_detail_001.txt","D:/work/","20.txt");
    }
    /**
     * 下載單個(gè)文件
     *
     * @param remoteFileName
     *            下載文件名
     * @param localPath
     *            本地保存目錄(以路徑符號(hào)結(jié)束)
     * @param localFileName
     *            保存文件名
     * @return
     */
    public static synchronized boolean downloadFile(String remotePath, String remoteFileName, String localPath, String localFileName) {
        logger.info(remotePath + "/" + remoteFileName + "/" + localPath + "/" + localFileName);
        try {
            if (sftp == null || !isConnected()) {
                connect();
            }
            sftp.cd(remotePath);
            File file = new File(localPath + localFileName);
            mkdirs(localPath + localFileName);
            sftp.get(remoteFileName, new FileOutputStream(file));
            return true;
        } catch (FileNotFoundException e) {
            logger.error("不存在文件,Path:" + remotePath + ",file:" + remoteFileName, e);
        } catch (SftpException e) {
            logger.error("下載文件處理異常,Path:" + remotePath + ",file:" + remoteFileName, e);
        } finally {
            disconnect();
        }
        return false;
    }
    
    /**
     * 上傳
     */
    public void uploadFile(String remotePath, String fileName, InputStream input) throws IOException, Exception {
        try {
            if (sftp == null) {
                connect();
            }
            // createDir(remotePath);
            mkDir(remotePath.replace(sftp.pwd(), ""));// 絕對(duì)路徑變?yōu)橄鄬?duì)路徑
            sftp.put(input, fileName);
        } catch (Exception e) {
            logger.error("文件上傳異常胚委!", e);
            throw new Exception("文件上傳異常:" + e.getMessage());
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (Exception e) {
                }
            }
            // disconnect();
        }
    }
    
    /**
     * 上傳單個(gè)文件
     *
     * @param remotePath
     *            遠(yuǎn)程保存目錄
     * @param remoteFileName
     *            保存文件名
     * @param localPath
     *            本地上傳目錄(以路徑符號(hào)結(jié)束)
     * @param localFileName
     *            上傳的文件名
     * @return
     */
    public boolean uploadFile(String remotePath, String remoteFileName, String localPath, String localFileName) {
        File fileInput = new File(localPath + localFileName);
        return uploadFile(remotePath, remoteFileName, fileInput);
    }
    
    /**
     * 上傳單個(gè)文件
     *
     * @param remotePath
     *            遠(yuǎn)程保存目錄
     * @param remoteFileName
     *            保存文件名
     * @param fileInput
     *            上傳的文件
     * @return
     */
    public boolean uploadFile(String remotePath, String remoteFileName, File fileInput) {
        FileInputStream in = null;
        try {
            in = new FileInputStream(fileInput);
            uploadFile(remotePath, remoteFileName, in);
            return true;
        } catch (Exception e) {
            logger.error("上傳單個(gè)文件異常", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.warn("關(guān)閉sftp資源異常", e);
                }
            }
        }
        return false;
    }
    
    /**
     * 創(chuàng)建目錄
     *
     * @param createpath
     * @return
     */
    private boolean createDir(String createpath) {
        try {
            if (isDirExist(createpath)) {
                this.sftp.cd(createpath);
                return true;
            }
            String[] pathArry = createpath.split("/");
            StringBuffer filePath = new StringBuffer("/");
            for (String path : pathArry) {
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(filePath.toString())) {
                    sftp.cd(filePath.toString());
                } else {
                    // 建立目錄
                    sftp.mkdir(filePath.toString());
                    // 進(jìn)入并設(shè)置為當(dāng)前目錄
                    sftp.cd(filePath.toString());
                }
            }
            return true;
        } catch (SftpException e) {
            logger.error("sftp創(chuàng)建目錄異常", e);
        }
        return false;
    }
    
    /**
     * 判斷目錄是否存在
     *
     * @param directory
     * @return
     */
    public boolean isDirExist(String directory) {
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            return sftpATTRS.isDir();
        } catch (Exception e) {
            // logger.error("sftp目錄isDirExist異常", e);
        }
        return false;
    }
    
    /**
     * 如果目錄不存在就創(chuàng)建目錄
     *
     * @param path
     */
    private static void mkdirs(String path) {
        File f = new File(path);
        String fs = f.getParent();
        f = new File(fs);
        if (!f.exists()) {
            f.mkdirs();
        }
    }
    
    public boolean deleteFile(String remotePath, String remoteFile) throws Exception {
        try {
            if (sftp == null)
                connect();
            if (openDir(remotePath)) {
                sftp.rm(remoteFile);
            }
            return true;
        } catch (SftpException e) {
            logger.error("刪除文件【" + remotePath + "/" + remoteFile + "】發(fā)生異常课竣!", e);
            throw e;
        }
    }
    
    /**
     * 創(chuàng)建文件夾
     *
     * @param dirName
     */
    public void mkDir(String dirName) {
        String[] dirs = dirName.split("/");
        try {
            String now = sftp.pwd();
            for (int i = 0; i < dirs.length; i++) {
                if (Strings.isNullOrEmpty(dirs[i]))
                    continue;
                boolean dirExists = openDir(dirs[i]);
                if (!dirExists) {
                    sftp.mkdir(dirs[i]);
                    sftp.cd(dirs[i]);
                }
            }
            // 進(jìn)入當(dāng)前目錄
            sftp.cd(now + "/" + dirName);
        } catch (SftpException e) {
            logger.error("mkDir Exception : " + e);
        }
    }
    
    /**
     * 打開(kāi)文件夾一層一層
     *
     * @param directory
     * @return
     */
    public boolean openDir(String directory) {
        try {
            logger.debug("opendir: {}", directory);
            sftp.cd(directory);
            return true;
        } catch (SftpException e) {
            logger.debug("openDir【" + directory + "】 Exception : " + e);
            return false;
        }
    }
    
    /**
     * 獲取輸出的out put stream
     * 
     * @param path
     * @param name
     * @return
     * @throws Exception
     */
    public OutputStream getUpLoadStream(String path, String name, String rcCode) throws Exception {
        if (sftp == null || !isConnected()) {
            connect();
        }
        String finalPath = path + rcCode;
        synchronized (CREATE_PATH_LOCK) {
            if (!openDir(finalPath)) {
                createDir(finalPath);
            }
        }
        sftp.cd(finalPath);
        return sftp.put(name);
    }
    
    private static Object CREATE_PATH_LOCK = new Object();
    
    public OutputStream getUpLoadStream(String path, String name) throws Exception {
        if (sftp == null || !isConnected()) {
            connect();
        }
        synchronized (CREATE_PATH_LOCK) {
            if (!openDir(path)) {
                createDir(path);
            }
        }
        sftp.cd(path);
        return sftp.put(name);
    }
    
    /**
     * 上傳 不關(guān)閉任何流
     */
    public void uploadFileNotClose(InputStream input, String remotePath, String fileName) throws IOException, Exception {
        try {
            if (sftp == null) {
                connect();
            }
            if (!openDir(remotePath)) {
                createDir(remotePath);
            }
            sftp.put(input, fileName);
        } catch (Exception e) {
            logger.error("文件上傳異常嘉赎!", e);
            throw new Exception("文件上傳異常:" + e.getMessage());
        }
    }
    
    /**
     * 上傳(input上傳完成,并未關(guān)閉,在外層調(diào)用處虛處理)
     */
    public void uploadFile(InputStream input, String remotePath, String fileName) throws IOException, Exception {
        try {
            if (sftp == null) {
                connect();
            }
            if (!openDir(remotePath)) {
                createDir(remotePath);
            }
            sftp.put(input, fileName);
        } catch (Exception e) {
            logger.error("文件上傳異常!", e);
            throw new Exception("文件上傳異常:" + e.getMessage());
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (Exception e) {
                }
            }
            disconnect();
        }
    }
    
    public String getHost() {
        return host;
    }
    
    public void setHost(String host) {
        this.host = host;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public int getPort() {
        return port;
    }
    
    public void setPort(int port) {
        this.port = port;
    }
    
    public ChannelSftp getSftp() {
        return sftp;
    }
    
    public void setSftp(ChannelSftp sftp) {
        this.sftp = sftp;
    }
    
    @SuppressWarnings("unchecked")
    public Vector<ChannelSftp.LsEntry> listFiles(String remotePath) throws Exception {
        Vector<ChannelSftp.LsEntry> vector = null;
        try {
            if (sftp == null)
                connect();
            sftp.cd("/");
            vector = sftp.ls(remotePath);
        } catch (SftpException e) {
            throw new Exception("list file error.", e);
        }
        return vector;
    }
    
    /**
     * 判斷文件是否存在
     * @param directory
     * @return
     */
    public boolean isFileExist(String directory) {
        boolean isDirExistFlag = false;
        try {
            if (sftp == null)
                connect();
            sftp.lstat(directory);
            isDirExistFlag = true;
        } catch (Exception e) {
            isDirExistFlag = false;
        }
        return isDirExistFlag;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末于樟,一起剝皮案震驚了整個(gè)濱河市公条,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迂曲,老刑警劉巖靶橱,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡关霸,警方通過(guò)查閱死者的電腦和手機(jī)传黄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)队寇,“玉大人膘掰,你說(shuō)我怎么就攤上這事〖亚玻” “怎么了识埋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)零渐。 經(jīng)常有香客問(wèn)我窒舟,道長(zhǎng),這世上最難降的妖魔是什么诵盼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任辜纲,我火速辦了婚禮,結(jié)果婚禮上拦耐,老公的妹妹穿的比我還像新娘耕腾。我一直安慰自己,他們只是感情好杀糯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布扫俺。 她就那樣靜靜地躺著,像睡著了一般固翰。 火紅的嫁衣襯著肌膚如雪狼纬。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天骂际,我揣著相機(jī)與錄音疗琉,去河邊找鬼。 笑死歉铝,一個(gè)胖子當(dāng)著我的面吹牛盈简,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播太示,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼柠贤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了类缤?” 一聲冷哼從身側(cè)響起臼勉,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎餐弱,沒(méi)想到半個(gè)月后宴霸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體囱晴,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年瓢谢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畸写。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恩闻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剧董,到底是詐尸還是另有隱情幢尚,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布翅楼,位于F島的核電站尉剩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毅臊。R本人自食惡果不足惜理茎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望管嬉。 院中可真熱鬧皂林,春花似錦、人聲如沸蚯撩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胎挎。三九已至沟启,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間犹菇,已是汗流浹背德迹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揭芍,地道東北人胳搞。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像称杨,于是被迫代替她去往敵國(guó)和親流酬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容