jcraft.ChannelSftp上传文件和文件夹,及ChannelSftp方法注释。

概述:
本文章主要是基于内容发布,通过ChannelSftp将文件复制到另一台机器涉及多线程调用,和怎么上传文件和文件夹,及ChannelSftp 中的语法说明。

POM

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

相关代码

public class sftpsynchronization {

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


    /**
     * 生产环境设计多线程大数据量时 ,会出现部分文件丢失,private static ChannelSftp channel = null,
     * 去掉static后即可解决,原因:channel 对象加了static后会导致 容器中只存在一个channel 所以多线程执行时,
     * 如果存在某一个线程关闭了channel ,会导致其他的线程执行报错;所以去掉static每个线程为单独的
     */
    private  ChannelSftp channel;

    private  Session session;

    /**
     * 规避多线程并发不断开问题
     */
    private  ThreadLocal<sftpsynchronization> sftpLocal = new ThreadLocal<sftpsynchronization>();


    /**
     * 创建sftp连接
     * @param map
     */
    public void connectServer(Map<String, Object> map) {
        try {
            // 创建JSch对象
            JSch jsch = new JSch();
            // 根据用户名,主机ip,端口获取一个Session对象
            String sftpPassword = CMSUtil.stringFormat(map.get("loginPwd"));
            session = jsch.getSession(CMSUtil.stringFormat(map.get("loginUser")), CMSUtil.stringFormat(map.get("targetServer")), CMSUtil.intFormat(CMSUtil.stringFormat(map.get("targetPort"))));
            if (sftpPassword != null) {
                // 设置密码
                session.setPassword(sftpPassword);
            }
            Properties configTemp = new Properties();
            configTemp.put("StrictHostKeyChecking", "no");
            // 为Session对象设置properties
            session.setConfig(configTemp);
            // 设置timeout时间
            session.setTimeout(60000);
            session.connect();
            // 通过Session建立链接
            // 打开SFTP通道
            channel = (ChannelSftp) session.openChannel("sftp");
            // 建立SFTP通道的连接
            channel.connect();

        } catch (JSchException e) {
//            //e.printStackTrace();
            logger.info("创建sftp连接失败");
        }
    }

   
    /**
     * 断开SFTP Channel、Session连接
     *
     * @param channel
     * @param session
     */
    public void closeChannel(ChannelSftp channel, Session session) {
        try {
            if (channel != null) {
                channel.disconnect();
                sftpLocal.set(null);
            }
            if (session != null) {
                session.disconnect();
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
    }

    /**
     * 判断sftp是否连接
     *
     * @return
     */
    public boolean isChannel() {
        try {
            if (channel.isConnected()) {
                return true;
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
        return false;
    }

    /**
     * 获取本地线程存储的sftp客户端
     * @param map
     * @return
     * @throws Exception
     */
    public sftpsynchronization getSftpUtil(Map<String,Object> map) throws Exception {
        sftpsynchronization sftpUtil = sftpLocal.get();
        if (null == sftpUtil || !sftpUtil.isChannel()) {
            sftpLocal.set(new sftpsynchronization(map));
        }
        return sftpLocal.get();
    }

    private sftpsynchronization(Map<String,Object> map) throws Exception {
        super();
        connectServer(map);
    }
	/**
     * 释放本地线程存储的sftp客户端
     *
     * @param sftpUtil
     */
    public void release(sftpsynchronization sftpUtil) {
        sftpUtil.closeChannel(sftpUtil.channel, sftpUtil.session);
    }
     /**
     * 判断目录是否存在
     * @param path
     * @return
     */
    public boolean isExistDir(String path){
        boolean  isExist=false;
        try {
            SftpATTRS sftpATTRS = channel.lstat(path);
            isExist = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isExist = false;
            }
        }
        return isExist;

    }
/**
     * 仅发布站点/栏目首页
     * 模板样式文件单个文件上传
     * 不需要同步附件和附图
     * @param map
     * @param localFile
     * @param datapath
     */
    public static void publishdistri(Map<String, Object> map, String localFile, String datapath) {
        //站点分发跟目录
        String dataPath = CMSUtil.stringFormat(map.get("dataPath"));
        sftpsynchronization sftpUtil = null;
        try {
            String newdatapah = datapath.replaceAll("//", "/");
            String localFilens = localFile.replaceAll("//", "/");
            sftpsynchronization sftp = new sftpsynchronization();
            sftpUtil = sftp.getSftpUtil(map);
            sftpUtil.copyFileNew(localFilens, dataPath, newdatapah);
        } catch (Exception e) {
            logger.error("仅发布站点/栏目首页SFTP站分发错误"+e.getMessage());
            //e.printStackTrace();
        } finally {
            sftpUtil.release(sftpUtil);
        }
    }

  /**
     * 上传文件
     * 文件内容复制
     * @param localFile  指定本地文件
     * @param remoteFile 配置服务路径
     * @param realpath   服务器具体路径
     * @throws SftpException
     */
    public void copyFileNew(String localFile, String remoteFile, String realpath) throws SftpException {
        File file = new File(localFile);
        //上传sftp目录
        String pathOut= remoteFile+"/" + realpath;
        if(file.exists()){
            try {
                channel.cd(pathOut);
            } catch (Exception e) {
                // 目录不存在,则创建文件夹
                String[] dirs = pathOut.split("/");
                String tempPath = "";
                int index = 0;
                mkdirDir(dirs, tempPath, dirs.length, index);
            }
            if (file.isDirectory()) {  //对象是否是文件夹
                File[] files = file.listFiles();
                if (files == null || files.length <= 0) {
                    logger.info("读取文件错误");
                }
                String  realpathtemp=realpath;
                //cd 目录
                String realpathcd="";
                for (File f : files) {
                    String fp = f.getAbsolutePath();
                    if (f.isDirectory()) {
                         realpathcd = remoteFile+"/" +realpathtemp + "/" + f.getName();
                        realpath = realpathtemp + "/" + f.getName();
                        try {
                            channel.cd(realpathcd);
                        } catch (Exception e) {
                            String pathOutTemp= remoteFile+"/" + realpath.replaceAll("//","/");
                            String[] dirs = pathOutTemp.split("/");
                            String tempPath = "";
                            int index = 0;
                            mkdirDir(dirs, tempPath, dirs.length, index);
                        }
                        copyFileNew(fp,remoteFile, realpath);
                    } else {
                        //OVERWRITE 覆盖文件
                        channel.put(fp, remoteFile + "/" + realpath, ChannelSftp.OVERWRITE);
                    }
                }
            } else {
                String fp = file.getAbsolutePath();
                channel.put(fp, remoteFile + "/" + realpath, ChannelSftp.OVERWRITE);
            }
        }
    }
    /**
     * 递归根据路径创建文件夹
     * @param dirs     根据 / 分隔后的数组文件夹名称
     * @param tempPath 拼接路径
     * @param length   文件夹的格式
     * @param index    数组下标
     * @return
     */
    public void mkdirDir(String[] dirs, String tempPath, int length, int index) {
        // 以"/a/b/c/d"为例按"/"分隔后,第0位是"";顾下标从1开始
        index++;
        if (index < length) {
            // 目录不存在,则创建文件夹
            tempPath += "/" + dirs[index];
        }
        try {
            channel.cd(tempPath);
            if (index < length) {
                mkdirDir(dirs, tempPath, length, index);
            }
        } catch (SftpException ex) {
            try {
                channel.mkdir(tempPath);
                channel.cd(tempPath);
            } catch (SftpException e) {
                logger.error("SFTP创建文件失败"+e.getMessage());
            }
            mkdirDir(dirs, tempPath, length, index);
        }
    }
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值