• java实操之使用jcraft进行sftp上传下载文件


      sftp作为临时的文件存储位置,在某些场合还是有其应景的,比如对账文件存放。需要提供一个上传的工具类。实现方法参考下:

    pom.xml中引入类库:

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

    sftp工具类和使用命令行是一样的操作方法,上传下载如下:

    public class SftpUploadTest {
    
        private ChannelSftp sftp = null;
    
        private Session sshSession = null;
    
        private String username;
    
        private String password;
    
        private String host;
    
        private int port;
    
        public SftpUploadTest(String username, String password, String host, int port) {
            this.username = username;
            this.password = password;
            this.host = host;
            this.port = port;
        }
    
        /**
         * 连接sftp服务器
         *
         * @return ChannelSftp sftp连接实例
         */
        public ChannelSftp connect() {
            info("-->sftp连接开始>>>>>> " + host + ":" + port + " >>>username=" + username);
            JSch jsch = new JSch();
            try {
                jsch.getSession(username, host, port);
                sshSession = jsch.getSession(username, host, port);
                sshSession.setPassword(password);
                Properties properties = new Properties();
                properties.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(properties);
                sshSession.connect();
                Channel channel = sshSession.openChannel("sftp");
                channel.connect();
                sftp = (ChannelSftp) channel;
                info(" ftp Connected to " + host + ":" + port);
            } catch (JSchException e) {
                throw new RuntimeException("sftp连接失败", e);
            }
            return sftp;
        }
    
        /**
         * 下载单个文件,如果指定文件名,则下载到文件名否则保持原有文件名
         *
         * @param remoteFilePath    远程文件路径 /tmp/xxx.txt || xxx.txt.zip
         * @param localFilePath     本地文件路径 如 D:\xxx.txt
         * @return 下载的文件
         */
        public File downloadFile(String remoteFilePath, String localFilePath) {
            info(">>>>>>>>>downloadFile--ftp下载文件" + remoteFilePath + "开始>>>>>>>>>>>>>");
            connect();
            String remoteFileName = "";
            // 远端目录确定以 / 作为目录格式
            String rFileSeparator = "/";
            int rDirNameSepIndex = remoteFilePath.lastIndexOf(rFileSeparator) + 1;
            String rDir = remoteFilePath.substring(0, rDirNameSepIndex);
            remoteFileName = remoteFilePath.substring(rDirNameSepIndex);
            if(localFilePath.endsWith(File.separator)) {
                localFilePath = localFilePath + (localFilePath.endsWith(File.separator) ? remoteFileName : "/" + remoteFileName);
            }
            File file = null;
            OutputStream output = null;
            try {
                file = new File(localFilePath);
                if (file.exists()) {
                    file.delete();
                }
                file.createNewFile();
                sftp.cd(rDir);
                output = new FileOutputStream(file);
                sftp.get(remoteFileName, output);
                info("===DownloadFile:" + remoteFileName + " success from sftp.");
            } catch (SftpException e) {
                error("ftp下载文件失败", e);
            } catch (FileNotFoundException e) {
                error("本地目录异常,请检查" + file.getPath(), e);
            } catch (IOException e) {
                error("创建本地文件失败" + file.getPath(), e);
            } finally {
                if (output != null) {
                    try {
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                disconnect();
            }
    
            info(">>>>>>>>>downloadFile--ftp下载文件结束>>>>>>>>>>>>>");
            return file;
        }
    
        /**
         * 上传单个文件,如果指正下载文件名则使用,否则保留原有文件名
         *
         * @param remoteFilePath    远程文件路径 /tmp/xxx.txt ||xxx.txt.zip
         * @param uploadFilePath    要上传的文件 如:D:\test\xxx.txt
         */
        public void uploadFile(String remoteFilePath, String uploadFilePath) {
            info(" begin uploadFile from:" + uploadFilePath +
                    ", to: " + remoteFilePath);
            FileInputStream in = null;
            connect();
            String remoteFileName = "";
            String remoteDir = remoteFilePath;
            String localFileName = "";
            // 远端目录确定以 / 作为目录格式
            String rFileSeparator = "/";
            if(remoteFilePath.endsWith(rFileSeparator)) {
                localFileName = uploadFilePath.substring(uploadFilePath.lastIndexOf(File.separator) + 1);
                remoteFileName = localFileName;
            } else {
                int fileNameDirSep = remoteFilePath.lastIndexOf(rFileSeparator) + 1;
                remoteDir = remoteFilePath.substring(0, fileNameDirSep);
                remoteFileName = remoteFilePath.substring(fileNameDirSep);
            }
            try {
                sftp.cd(remoteDir);
            } catch (SftpException e) {
                try {
                    sftp.mkdir(remoteDir);
                    sftp.cd(remoteDir);
                } catch (SftpException e1) {
                    error("ftp创建文件路径失败,路径为" + remoteDir);
                    throw new RuntimeException("ftp创建文件路径失败" + remoteDir);
                }
            }
            File file = new File(uploadFilePath);
            try {
                in = new FileInputStream(file);
                sftp.put(in, remoteFileName);
            } catch (FileNotFoundException e) {
                error("文件不存在-->" + uploadFilePath);
            } catch (SftpException e) {
                error("sftp异常-->", e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        info("Close stream error." + e.getMessage());
                    }
                }
                disconnect();
            }
            info(">>>>>>>>>uploadFile--ftp上传文件结束>>>>>>>>>>>>>");
        }
    
        /**
         * 关闭连接
         */
        public void disconnect() {
            if (this.sftp != null) {
                if (this.sftp.isConnected()) {
                    this.sftp.disconnect();
                    this.sftp = null;
                    info("sftp 连接已关闭!");
                }
            }
            if (this.sshSession != null) {
                if (this.sshSession.isConnected()) {
                    this.sshSession.disconnect();
                    this.sshSession = null;
                    info("sshSession 连接已关闭!");
                }
            }
        }
        private void info(String msg) {
            System.out.println("info: " + msg);
        }
    
        private void error(String msg) {
            error(msg, null);
        }
    
        private void error(String msg, Throwable e) {
            System.out.println("error: " + msg);
            if(e != null) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws Exception {
            SftpUploadTest uploadTest = new SftpUploadTest("root", "123", "10.40.10.17", 52766);
            uploadTest.uploadFile("/tmp/" + "readme-" + System.currentTimeMillis() + ".txt", "C:\Users\xx\Desktop\sample\readme.txt");
            uploadTest.downloadFile("/tmp/readme.txt", "C:\Users\xx\Desktop\sample\readme-" + System.currentTimeMillis() + ".txt");
        }
    }

      使用时,可根据需要进行连接的适时释放!也可能为了安全需要,添加一些额外的安全指令!

      sftp文件操作的命令罗列如下参考:

    sftp常用的为上传下载

    # get
    # 从远程服务器上下载一个文件存放到本地,如下:
    # 先通过lcd切换到本地那个目录下,然后通过get file
    >> lcd d: #表示切换到本地的d盘下
    >> get ./test.sql   #这样就将当前文件下载本地的d盘下
    # put
    # 是将本地的文件上传到远程服务器上,如下:
    >> put #在windows下弹出选择文件的窗口
    # lcd
    # 先通过lcd切换到本地那个目录下
    >> lcd c: #表示切换到本地的c盘下
    # lls
    #显示当前目录下的所有文件
    >> pwd        #显示当前目录
  • 相关阅读:
    【基础】Attribute的妙用
    【翻译】.Net Core的意义
    【基础】迭代器详解
    【总结】数据库索引的实现原理
    【实践】基于接口的插件机制
    【总结】设计模式应用之单例模式
    【基础】多线程更新窗体UI的若干方法
    【基础】MVC路由规则
    Mybatis 分页:Pagehelper + 拦截器实现
    这四种对象属性拷贝方式,你都知道吗?
  • 原文地址:https://www.cnblogs.com/yougewe/p/9580350.html
Copyright © 2020-2023  润新知