Java使用sftp文件服务器

1.简介

在工作中,对接第三方服务时,往往存在文件的传输使用,使用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) {
        }
    }
}
    }

    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) {
        }
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用Java实现SFTP文件传输,可以使用JSch库。以下是一个简单的示例代码,演示如何使用JSch实现SFTP上传文件到资源服务器: ```java import com.jcraft.jsch.*; public class SFTPUploader { public static void main(String[] args) { String host = "sftp.example.com"; String username = "your-username"; String password = "your-password"; int port = 22; String localFilePath = "/path/to/local/file.txt"; String remoteFilePath = "/path/to/remote/file.txt"; JSch jsch = new JSch(); Session session = null; try { session = jsch.getSession(username, host, port); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword(password); session.connect(); ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); channelSftp.put(localFilePath, remoteFilePath); channelSftp.disconnect(); } catch (JSchException | SftpException e) { e.printStackTrace(); } finally { if (session != null) { session.disconnect(); } } } } ``` 在这个示例代码中,`host`是资源服务器的主机名,`username`和`password`是SFTP登录凭据,`port`是SFTP端口,默认为22。`localFilePath`是本地文件路径,`remoteFilePath`是远程文件路径。 `JSch`实例用于创建SFTP会话,`Session`实例用于连接到资源服务器。在此示例代码中,我们使用`StrictHostKeyChecking`配置来禁用主机密钥检查。接下来,我们打开一个SFTP通道,并将本地文件上传到远程服务器。 请注意,如果您需要进行多个文件传输,则应该重用单个`Session`和`ChannelSftp`实例,而不是每次传输都打开和关闭新的会话和通道。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃榴莲不吐葡萄皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值