java使用sftp文件服务器

  在工作中,对接第三方服务时,往往存在文件的传输使用,使用stfp是一种简单有效的方式,可以对文件进行上传和下载。下面是使用sftp文件服务器的demo,可以作为工具类放入项目中,即可简单上手和使用。

  • FtpClient.java
public class FtpUtil {
    private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);

    public FtpUtil() {
    }
    
public static enum ProxyType {
        HTTP;

        private ProxyType() {
        }
    }

    public static class FtpDto implements Serializable {
        private static final long serialVersionUID = 2610830652396624141L;
        private String ip;
        private int port;
        private String user;
        private String password;
        private String remoteDir;
        private String localFilePathName;
        private String remoteFileName;
        private FtpUtil.ProxyType proxyType;
        private String proxyHost;
        private int proxyPort;

        public FtpDto() {
        }

        public String getIp() {
            return this.ip;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public int getPort() {
            return this.port;
        }

        public void setPort(int port) {
            this.port = port;
        }

        public String getUser() {
            return this.user;
        }

        public void setUser(String user) {
            this.user = user;
        }

        public String getPassword() {
            return this.password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getRemoteDir() {
            return this.remoteDir;
        }

        public void setRemoteDir(String remoteDir) {
            this.remoteDir = remoteDir;
        }

        public String getLocalFilePathName() {
            return this.localFilePathName;
        }

        public void setLocalFilePathName(String localFilePathName) {
            this.localFilePathName = localFilePathName;
        }

        public String getRemoteFileName() {
            return this.remoteFileName;
        }

        public void setRemoteFileName(String remoteFileName) {
            this.remoteFileName = remoteFileName;
        }

        public FtpUtil.ProxyType getProxyType() {
            return this.proxyType;
        }

        public void setProxyType(FtpUtil.ProxyType proxyType) {
            this.proxyType = proxyType;
        }

        public String getProxyHost() {
            return this.proxyHost;
        }

        public void setProxyHost(String proxyHost) {
            this.proxyHost = proxyHost;
        }

        public int getProxyPort() {
            return this.proxyPort;
        }

        public void setProxyPort(int proxyPort) {
            this.proxyPort = proxyPort;
        }
    }
}
  • SftpClient.java
public class SftpClient {

    /**
     * 上传文件
     * 
     * @param ip
     * @param port
     * @param user
     * @param password
     * @param localFilePath
     * @param remoteDir
     * @param remoteFileName
     * @param useProxy
     */
    public static final String PROXY_HOST = "XXXX";
    public static final int PROXY_PORT = XX;

    public static void upload(String ip, int port, String user, String password, String localFilePath, String remoteDir,
                              String remoteFileName, boolean useProxy) {
        FtpDto ftpDto = new FtpDto();
        ftpDto.setIp(ip);
        ftpDto.setPort(port);
        ftpDto.setUser(user);
        ftpDto.setPassword(password);
        if (useProxy) {
            ftpDto.setProxyType(ProxyType.HTTP);
            ftpDto.setProxyHost(PROXY_HOST);
            ftpDto.setProxyPort(PROXY_PORT);
        }

        ftpDto.setRemoteDir(remoteDir);
        ftpDto.setLocalFilePathName(localFilePath);
        ftpDto.setRemoteFileName(remoteFileName);

        SftpUtil.upload(ftpDto);
    }

    /**
     * 下载文件
     * 
     * @param ip
     * @param port
     * @param user
     * @param password
     * @param localFilePath
     * @param remoteDir
     * @param remoteFileName
     * @param useProxy
     */
    public static void download(String ip, int port, String user, String password, String localFilePath,
                                String remoteDir, String remoteFileName, boolean useProxy) {
        FtpDto ftpDto = new FtpDto();
        ftpDto.setIp(ip);
        ftpDto.setPort(port);
        ftpDto.setUser(user);
        ftpDto.setPassword(password);
        if (useProxy) {
            ftpDto.setProxyType(ProxyType.HTTP);
            ftpDto.setProxyHost(PROXY_HOST);
            ftpDto.setProxyPort(PROXY_PORT);
        }

        ftpDto.setRemoteDir(remoteDir);
        ftpDto.setLocalFilePathName(localFilePath);
        ftpDto.setRemoteFileName(remoteFileName);

        SftpUtil.download(ftpDto);
    }
}
  • SftpUtil.java
    pom依赖
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
        </dependency>
import com.jcraft.jsch.*;

public class SftpUtil {

    private static int timeout = 60000;

    private static final Logger logger  = LoggerFactory.getLogger(SftpUtil.class);

    private static ChannelItem getChannel(FtpDto ftpDto) throws Exception {
        JSch jsch = new JSch();
        Session session = jsch.getSession(ftpDto.getUser(), ftpDto.getIp(), ftpDto.getPort());
        session.setPassword(ftpDto.getPassword());
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.setTimeout(timeout);
        if (!StringUtils.isBlank(ftpDto.getProxyHost())) {
            ProxyHTTP proxy = new ProxyHTTP(ftpDto.getProxyHost(), ftpDto.getProxyPort());
            session.setProxy(proxy);
        }
        session.connect();
        Channel channel = session.openChannel("sftp");
        channel.connect();

        ChannelItem channelItem = new ChannelItem();
        channelItem.setChannel((ChannelSftp) channel);
        channelItem.setSession(session);
        return channelItem;
    }

    private static void closeChannel(ChannelItem channelItem) {
        try {
            if (channelItem.getSession() != null) {
                channelItem.getSession().disconnect();
            }
        } catch (Exception e1) {
            logger.warn("退出SFTP管道异常");
        }
        try {
            if (channelItem.getChannel() != null) {
                channelItem.getChannel().disconnect();
            }
        } catch (Exception e1) {
            logger.warn("退出SFTP管道异常");
        }
    }

    public static void upload(FtpDto ftpDto) {
        upload(ftpDto, null);
    }

    public static void upload(FtpDto ftpDto, String capSubCodePath) {
        logger.info("开始SFTP文件上传:{}", ftpDto.toString());
        ChannelSftp chSftp = null;
        ChannelItem channelItem = null;
        InputStream is = null;
        try {
            channelItem = SftpUtil.getChannel(ftpDto);
            chSftp = (ChannelSftp) channelItem.getChannel();
            try {
                if (StringUtils.isNotEmpty(capSubCodePath)) {
                    if (!isDirExist(chSftp, capSubCodePath)) {
                        chSftp.mkdir(capSubCodePath);
                    }
                }
                if (!isDirExist(chSftp, ftpDto.getRemoteDir())) {
                    createDir(chSftp, ftpDto.getRemoteDir());
                }
                logger.info("创建目录成功:{}", ftpDto.getRemoteDir());
            } catch (SftpException e) {
                logger.error("创建目录失败:{}", ftpDto.getRemoteDir(), e);
            }

            String upPath = ftpDto.getRemoteDir();
            if (!(upPath.endsWith(File.separator) || upPath.endsWith("/"))) {
                upPath = upPath.concat(File.separator);
            }
            upPath = upPath.concat(ftpDto.getRemoteFileName());
            OutputStream out = chSftp.put(upPath, ChannelSftp.OVERWRITE);
            byte[] buff = new byte[1024 * 256];
            int read;
            if (out != null) {
                is = new FileInputStream(ftpDto.getLocalFilePathName());
                do {
                    read = is.read(buff, 0, buff.length);
                    if (read > 0) {
                        out.write(buff, 0, read);
                    }
                    out.flush();
                } while (read >= 0);
            }
        } catch (Exception e) {
            logger.error("SFTP文件上传失败", e);
            throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { ftpDto.getRemoteFileName() + "文件上传失败" }, e.getMessage());
        } finally {
            if (chSftp != null) {
                try {
                    chSftp.quit();
                } catch (Exception e) {
                    logger.warn("退出SFTP管道异常");
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    logger.warn("关闭InputStream异常");
                }
            }
            closeChannel(channelItem);
        }
        logger.info("成功SFTP文件上传:{}", ftpDto.getLocalFilePathName());
    }

    /**
     * 批量文件上传
     * 
     * @param ftpDto
     * @return
     * @throws Exception
     */
    public static boolean batchUploadFile(List<FtpDto> ftpDtoList) throws Exception {
        ChannelItem channelItem = SftpUtil.getChannel(ftpDtoList.get(0));
        try {
            ChannelSftp chSftp = (ChannelSftp) channelItem.getChannel();
            boolean flag = batchUploadFile(chSftp, ftpDtoList);
            return flag;
        } catch (Exception e) {
            logger.error("SftpUtil.batchUploadFile上传异常:", e);
        } finally {
            closeChannel(channelItem);
        }
        return false;
    }

    /**
     * 批量文件上传
     * 
     * @param ftpDto
     * @return
     */
    private static boolean batchUploadFile(ChannelSftp chSftp, List<FtpDto> ftpDtoList) {
        boolean doneFlag = false;
        try {
            for (FtpDto ftpDto : ftpDtoList) {
                boolean flag = uploadFile(chSftp, ftpDto);
                if (!flag) {
                    doneFlag = false;
                    logger.error("SftpUtil.batchUploadFile上传失败:FilePathName:{}", ftpDto.getLocalFilePathName());
                    break;
                } else {
                    doneFlag = true;
                    logger.info("SftpUtil.batchUploadFile上传成功:FilePathName:{}", ftpDto.getLocalFilePathName());
                }
            }
        } catch (Exception e) {
            doneFlag = false;
            logger.error("SftpUtil.batchUploadFile上传异常:", e);
        }
        return doneFlag;

    }

    private static boolean uploadFile(ChannelSftp chSftp, FtpDto ftpDto) {
        InputStream is = null;
        try {
            if (!isDirExist(chSftp, ftpDto.getRemoteDir())) {
                createDir(chSftp, ftpDto.getRemoteDir());
            }
            OutputStream out = chSftp.put(ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()), ChannelSftp.OVERWRITE);
            byte[] buff = new byte[1024 * 256];
            int read;
            if (out != null) {
                is = new FileInputStream(ftpDto.getLocalFilePathName());
                do {
                    read = is.read(buff, 0, buff.length);
                    if (read > 0) {
                        out.write(buff, 0, read);
                    }
                    out.flush();
                } while (read >= 0);
            }
            return true;
        } catch (Exception e) {
            logger.error("SftpUtil文件上传上传异常:", e);
            throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { ftpDto.getRemoteFileName() + "文件上传失败" }, e.getMessage());
        } finally {
            if (chSftp != null) {
                try {
                    chSftp.quit();
                } catch (Exception e) {
                    logger.warn("退出SFTP管道异常");
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    logger.warn("关闭InputStream异常");
                }
            }
        }
    }

    private static void createDir(ChannelSftp chSftp, String directory) {
        try {
            if (directory == null) {
                return;
            }
            if (isDirExist(chSftp, directory)) {
                chSftp.cd(directory);
            }
            String pathArry[] = directory.split("/");
            StringBuffer filePath = new StringBuffer("/");
            for (String path : pathArry) {
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(chSftp, filePath.toString())) {
                    logger.info("进入并设置为当前目录0:{}", filePath.toString());
                    chSftp.cd(filePath.toString());
                } else {
                    // 建立目录
                    logger.info("建立目录:{}", filePath.toString());
                    chSftp.mkdir(filePath.toString());
                    // 进入并设置为当前目录
                    logger.info("进入并设置为当前目录:{}", filePath.toString());
                    chSftp.cd(filePath.toString());
                }
            }
            chSftp.cd(directory);
        } catch (SftpException e) {
            logger.error("创建目录失败:{}", directory, e);
        }
    }

    private static boolean isDirExist(ChannelSftp chSftp, String directory) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = chSftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }

    public static void download(FtpDto ftpDto) {
        logger.info("开始SFTP文件下载:{}", ftpDto.toString());
        ChannelSftp chSftp = null;
        ChannelItem channelItem = null;
        OutputStream out = null;
        try {
            channelItem = SftpUtil.getChannel(ftpDto);
            chSftp = (ChannelSftp) channelItem.getChannel();
            InputStream is = chSftp.get(ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()));
            out = new FileOutputStream(ftpDto.getLocalFilePathName());
            byte[] buff = new byte[1024 * 2];
            int read;
            if (is != null) {
                do {
                    read = is.read(buff, 0, buff.length);
                    if (read > 0) {
                        out.write(buff, 0, read);
                    }
                    out.flush();
                } while (read >= 0);
            }
        } catch (Exception e) {
            logger.warn("SFTP文件下载失败:" + ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()), e);
            throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { "文件下载失败" }, ftpDto.getRemoteFileName());
        } finally {
            if (chSftp != null) {
                try {
                    chSftp.quit();
                } catch (Exception e) {
                    logger.warn("退出SFTP管道异常");
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    logger.warn("关闭OutputStream异常");
                }
            }
            closeChannel(channelItem);
        }
        logger.info("成功SFTP文件下载:{}", ftpDto.getLocalFilePathName());
    }

    static class ChannelItem {

        Session session;
        Channel channel;

        public Session getSession() {
            return session;
        }

        public void setSession(Session session) {
            this.session = session;
        }

        public Channel getChannel() {
            return channel;
        }

        public void setChannel(Channel channel) {
            this.channel = channel;
        }
    }

    public static class MyProgressMonitor implements SftpProgressMonitor {

        private long transfered;

        public MyProgressMonitor(long transfered) {
            this.transfered = transfered;
        }

        @Override
        public boolean count(long count) {
            transfered = transfered + count;
            return true;
        }

        @Override
        public void end() {
        }

        @Override
        public void init(int op, String src, String dest, long max) {
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容