Jsch上传本地目录文件到服务器

news2024/11/15 17:35:53

文章目录

  • 1.Jsch简介
    • 1.1 什么是Jsch
    • 1.2 Jsch使用步骤和简单示例
  • 2.技术关键点
  • 3.Jsch实战
    • 3.1 maven依赖
    • 3.2 功能实现
    • 3.3 效果
    • 3.4 封装工具类
  • 4.总结

摘要: 在一些框架开发工作中,需要为项目使用说明文档,来指导用户如何正确使用框架。比如通过markdown编写文档,同时将文档及图片等静态资源发布到nginx服务器。往往采用编译时候结合cicd脚本一起构建,推送服务器,但无法满足日常研发实时发布需要,本文介绍通过Jsch复制本地文件目录,到资源服务器得方法。

关键词: jsch;目录上传

1.Jsch简介

1.1 什么是Jsch

Jsch 是 Java Secure Channel 的缩写,是一个纯 Java 实现的 SSH2 协议客户端库。它允许在 Java 应用程序中建立与 SSH 服务器的安全连接,并进行文件传输、远程命令执行等操作.
以下是一些Jsch的主要特点和技术应用:

  1. SSH 连接:JSch 支持通过多种身份验证方法(如密码认证、公钥认证等)建立到 SSH 服务器的安全连接。
  2. 文件传输:JSch 实现了 SCP(Secure Copy)和 SFTP(SSH File Transfer Protocol)协议,允许在本地计算机和远程服务器之间进行文件的上传、下载和管理。
  3. 远程命令执行:JSch 允许在远程服务器上执行命令,可以通过打开远程 Shell 会话来执行命令并获取输出或处理错误。
  4. 端口转发:JSch 支持端口转发功能,可以将本地端口与远程端口关联,用于安全通信和访问受限资源。

1.2 Jsch使用步骤和简单示例

使用Jsch进行SSH连接和执行远程命令的一般步骤如下:

  1. 导入Jsch库: 首先需要将Jsch库添加到Java项目的依赖中。
  2. 创建Session对象: 使用Jsch库创建一个Session对象,该对象表示与远程服务器的会话。需要指定远程服务器的主机名、用户名和密码或者SSH密钥等认证信息。
  3. 连接到远程服务器: 调用Session对象的connect方法来连接到远程服务器。
  4. 创建Channel对象: 使用Session对象创建一个Channel对象,该对象表示与远程服务器的通信通道,可以是执行远程命令的Shell通道或者用于文件传输的SFTP通道等。
  5. 打开Channel: 调用Channel对象的open方法来打开通道。
  6. 执行操作: 根据需要执行相应的操作,例如执行远程命令、上传或下载文件等。
  7. 关闭通道和会话: 操作完成后,需要关闭Channel和Session对象,释放资源

下面是一个简单的示例代码,演示了如何使用Jsch连接到远程服务器并执行一个简单的命令:

import com.jcraft.jsch.*;

public class SSHExample {
    public static void main(String[] args) {
        String host = "remote_host";
        String user = "username";
        String password = "password";
        String command = "ls -l";

        try {
            // 创建JSch对象
            JSch jsch = new JSch();
            
            // 创建Session对象
            Session session = jsch.getSession(user, host, 22);
            
            // 设置密码
            session.setPassword(password);
            
            // 取消默认的HostKey检查
            session.setConfig("StrictHostKeyChecking", "no");
            
            // 连接到远程服务器
            session.connect();
            
            // 打开通道
            Channel channel = session.openChannel("exec");
            
            // 设置命令
            ((ChannelExec) channel).setCommand(command);
            
            // 获取输入流
            channel.setInputStream(null);
            
            // 获取输出流
            ((ChannelExec) channel).setErrStream(System.err);
            
            // 连接通道
            channel.connect();
            
            // 读取命令输出
            InputStream in = channel.getInputStream();
            byte[] buffer = new byte[1024];
            while (true) {
                while (in.available() > 0) {
                    int bytesRead = in.read(buffer, 0, 1024);
                    if (bytesRead < 0) break;
                    System.out.print(new String(buffer, 0, bytesRead));
                }
                if (channel.isClosed()) {
                    if (in.available() > 0) continue;
                    System.out.println("Exit Status: " + channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {
                }
            }
            
            // 关闭通道和会话
            channel.disconnect();
            session.disconnect();
        } catch (JSchException | IOException e) {
            e.printStackTrace();
        }
    }
}

2.技术关键点

使用jsch的sftp功能实现单文件上传难度不大,而本地目录上传问题本质上是多目录多的文件批量上传文件问题,需要额外考虑细节问题如下:

  1. 服务器目标根目录,不一定存在存在,需要创建。
  2. 本地目录中还包含子目录,需要在父级目录中上传文件,同时判断子目录。

流程如下:

2.复制本地文件到远程目录
是否是文件
读取文件/目录
创建远程相对目录
上传文件到远程相对目录
遍历文件/子目录递归
开始
连接到目标主机
打开SFTP通道
1.创建目标远程目录
关闭连接
结束

3.Jsch实战

3.1 maven依赖

        <!--SSH-->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>

3.2 功能实现

v1.0 基础可以用版本

import com.jcraft.jsch.*;

import java.io.File;

public class LocalToRemoteFileCopy {

    public static void main(String[] args) {
        String localPath = "D:\\git\\demo\\note_codeup\\docs";
        String remotePath = "/root/test/docker-compose-nginx/data/docs";
        String hostname = "192.168.100.4";
        int port = 22;
        String username = "root";
        String password = "123456";

        copyLocalToRemote(localPath, remotePath, hostname, port, username, password);
    }

    private static void copyLocalToRemote(String localPath, String remotePath, String hostname, int port,
                                          String username, String password) {
        JSch jsch = new JSch();
        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            // 连接到目标主机
            session = jsch.getSession(username, hostname, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 打开目标主机的 SFTP 通道
            Channel channel = session.openChannel("sftp");
            channel.connect();
            channelSftp = (ChannelSftp) channel;

            // 递归创建远程目录(如果不存在)
            createRemoteDirectories(channelSftp, remotePath);

            // 从本地复制文件到目标主机
            copyLocalDirectory(new File(localPath), channelSftp, remotePath);

            // 关闭连接
            channelSftp.disconnect();
            session.disconnect();
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
    }

    // 递归创建远程目录(如果不存在)
    private static void createRemoteDirectories(ChannelSftp channelSftp, String remoteDirectory) throws SftpException {
        String[] dirs = remoteDirectory.split("/");
        String currentDir = "/";
        for (String dir : dirs) {
            if (!dir.isEmpty()) {
                currentDir += dir + "/";
                try {
                    channelSftp.stat(currentDir); // 检查目录是否存在
                } catch (SftpException e) {
                    // 目录不存在,创建目录
                    channelSftp.mkdir(currentDir);
                }
            }
        }
    }

    // 递归上传本地文件到远程目录
    private static void copyLocalDirectory(File localFile, ChannelSftp channelSftp, String remotePath)
            throws SftpException {
        if (localFile.isDirectory()) {
            // 获取本地目录下的所有文件和子目录
            File[] files = localFile.listFiles();
            if (files != null) {
                for (File file : files) {
                    copyLocalDirectory(file, channelSftp, remotePath + "/" + localFile.getName());
                }
            }
        } else if (localFile.isFile()) {
            // 上传文件,并递归创建远程目录(如果不存在)
            createRemoteDirectories(channelSftp, remotePath);
            System.out.println(localFile.getAbsolutePath() + " ==> " + remotePath + "/" + localFile.getName());
            channelSftp.put(localFile.getAbsolutePath(), remotePath + "/" + localFile.getName());
        }
    }
}

3.3 效果

image.png

3.4 封装工具类

import com.jcraft.jsch.*;

import java.io.File;

public class SftpUtils {

    public static void copyLocalToRemote(String localPath, String remotePath, String hostname, int port,
                                         String username, String password) {
        JSch jsch = new JSch();
        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            // 连接到目标主机
            session = jsch.getSession(username, hostname, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 打开目标主机的 SFTP 通道
            Channel channel = session.openChannel("sftp");
            channel.connect();
            channelSftp = (ChannelSftp) channel;

            // 递归创建远程目录(如果不存在)
            createRemoteDirectories(channelSftp, remotePath);

            // 从本地复制文件到目标主机
            copyLocalDirectory(new File(localPath), channelSftp, remotePath);

            // 关闭连接
            channelSftp.disconnect();
            session.disconnect();
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
    }

    // 递归创建远程目录(如果不存在)
    private static void createRemoteDirectories(ChannelSftp channelSftp, String remoteDirectory) throws SftpException {
        String[] dirs = remoteDirectory.split("/");
        String currentDir = "/";
        for (String dir : dirs) {
            if (!dir.isEmpty()) {
                currentDir += dir + "/";
                try {
                    channelSftp.stat(currentDir); // 检查目录是否存在
                } catch (SftpException e) {
                    // 目录不存在,创建目录
                    channelSftp.mkdir(currentDir);
                }
            }
        }
    }

    // 递归上传本地文件到远程目录
    private static void copyLocalDirectory(File localFile, ChannelSftp channelSftp, String remotePath)
            throws SftpException {
        if (localFile.isDirectory()) {
            // 获取本地目录下的所有文件和子目录
            File[] files = localFile.listFiles();
            if (files != null) {
                for (File file : files) {
                    copyLocalDirectory(file, channelSftp, remotePath + "/" + localFile.getName());
                }
            }
        } else if (localFile.isFile()) {
            // 上传文件,并递归创建远程目录(如果不存在)
            createRemoteDirectories(channelSftp, remotePath);
            System.out.println(localFile.getAbsolutePath() + " ==> " + remotePath + "/" + localFile.getName());
            channelSftp.put(localFile.getAbsolutePath(), remotePath + "/" + localFile.getName());
        }
    }
}

4.总结

本文通过分析,使用jsch技术实现本地文件目录整体拷贝至服务器指定目录需求,分析关键步骤以及实现细节,并最终封装工具类。为后续实现,静态资源发布部署,文件目录定时同步功能,提供技术实现支撑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1813010.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

易舟云:让中小企业财务管理变得触手可及

在现代企业运营中&#xff0c;财务管理的精准和高效至关重要。对于中小企业来说&#xff0c;一款专业且易于使用的财务软件更是必不可少的工具。今天&#xff0c;我们就来详细了解一款深受中小企业喜爱的财务软件——易舟云。 财务管理的云端革命 随着云技术的发展&#xff0c;…

EVA-CLIP:在规模上改进CLIP的训练技术

摘要 对比性语言-图像预训练&#xff0c;简称CLIP&#xff0c;因其在各种场景中的潜力而备受关注。在本文中&#xff0c;我们提出了EVA-CLIP&#xff0c;一系列模型&#xff0c;这些模型显著提高了CLIP训练的效率和有效性。我们的方法结合了新的表示学习、优化和增强技术&…

Phaser-圆形路径

使用 Phaser 创建一个简单的路径动画 Phaser 是一个强大的 HTML5 游戏框架&#xff0c;适合用于开发 2D 游戏。在本文中&#xff0c;我们将展示如何使用 Phaser 创建一个简单的动画示例&#xff0c;其中一个红色的圆沿着椭圆路径移动。该示例将帮助你理解如何在 Phaser 中使用…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

Redis】Redis主从复制(二)————主从结构/流程

目录 回顾slaveof 命令断开主从复制关系切换主从复制关系只读网络延迟问题应对措施补充 主从结构一主一从结构问题改进 一主多从结构树形主从主从切换结构 主从复制流程简单来记关于数据同步两个参数replicationidoffset. psync 运行流程全量复制和部分复制全量复制流程&#x…

在镜像中添加Git提交号

文章目录 前言环境介绍思路内核cpuinfo中添加Git提交号修改setup.c获取Git提交号和生成GIT_COMMIT_INFO宏继续修改内核setup.c验证 内核设备树中添加Git提交号修改设备树验证 U-Boot版本号添加Git提交号U-Boot配置修改setlocalversion脚本验证 前言 在镜像中加入Git提交号&…

mysql和redis的双写一致性问题

一&#xff0c;使用方案 在使用redis作为缓存的场景下&#xff0c;我们一般使用流程如下 二&#xff0c;更新数据场景 我们此时修改个某条数据&#xff0c;如何保证mysql数据库和redis缓存中的数据一致呢&#xff1f; 按照常规思路有四种办法&#xff0c;1.先更新mysql数据&a…

计划任务!!!

目录 一、补充 1.1关闭防火墙 1.2安装php 二、计划任务 2.1at一次性计划任务 2.2周期性计划任务&#xff08;crontab&#xff09; 上篇我们学了rpm安装、yum安装还有编译安装。今天我们先补充一下上篇的东西再学习计划任务 一、补充 1.1关闭防火墙 systemctl stop fir…

亚马逊竞品分析之如何查找竞品

初选之后,要对产品进行竞品分析,查找竞品的方法: 1.Best Seller榜单查找 进入到该类目的BS榜单去找跟你选中的产品的竞品 看完BS榜单会找出一部分竞品 这个找相似也可以点击,是插件的一个以图搜图的功能,不过有的时候不太好使,某些同款产品可能搜不到。 Edge浏览器搭…

原生js写table表格固定表头

给表头添加以下属性 table表格写法参考 jquery写表格 手动合并单元格-CSDN博客 jquery写表格&#xff08;带滚动条&#xff09;_row.append($(<td>)-CSDN博客

面试题:什么是线程的上下文切换?

线程的上下文切换是指在操作系统中&#xff0c;CPU从执行一个线程的任务切换到执行另一个线程任务的过程。在现代操作系统中&#xff0c;为了实现多任务处理和充分利用CPU资源&#xff0c;会同时管理多个线程的执行。由于CPU在任意时刻只能执行一个线程&#xff0c;因此需要在这…

LeetCode 算法:螺旋矩阵c++

原题链接&#x1f517;&#xff1a;螺旋矩阵 难度&#xff1a;中等⭐️⭐️ 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&…

西南交通大学【操作系统实验2】

实验目的 本实验要求学生了解什么是信号&#xff0c;掌握软中断的基本原理&#xff1b;掌握中断信号的使用、进程的创建以及系统计时器的使用。通过对本实验的学习&#xff0c;学生能够学会进程的创建方法&#xff0c;更能加深对Linux中的信号机制的认识&#xff0c;并会使用软…

【Qt 学习笔记】Qt窗口 | 标准对话框 | 消息对话框QMessageBox

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 标准对话框 | 消息对话框QMessageBox 文章编号&#xff1a;Q…

基于长短期记忆网络 LSTM 的下一个单词预测

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

Parallels Desktop 19虚拟机助你一机多用

Parallels Desktop 19 mac虚拟机是一款功能强大且易于使用的虚拟化软件&#xff0c;它允许用户在Mac电脑上同时运行Windows、Linux和其他多种操作系统&#xff0c;为用户提供了极大的灵活性和兼容性。 Parallels Desktop 19获取 这款虚拟机软件具有直观易用的界面&#xff0c;…

云动态摘要 2024-06-11

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 [低至1折]腾讯混元大模型产品特惠 腾讯云 2024-06-06 腾讯混元大模型产品特惠,新用户1折起! 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器ECS试用产品续用 最新产品更新 云服务器运维监…

您的计算机时间有误

问题 使用 apt update 更新软件时报错&#xff0c;提示 Release 文件已过期。 另外还发现&#xff0c;命令行 Ping 百度是通的&#xff0c;但是通过浏览器无法访问百度网站 解决 浏览器已经有很明确的的提示了&#xff1a;您的计算机时间有误。 所以&#xff0c;同步一下…

【总线】设计fpga系统时,为什么要使用总线?

目录 为什么用总线 为什么选择AMBA 总结 系列文章 【总线】AMBA总线架构的发展历程-CSDN博客 【总线】设计fpga系统时&#xff0c;为什么要使用总线&#xff1f;-CSDN博客 为什么用总线 在FPGA系统设计中&#xff0c;使用总线是为了实现组件间的高效互联与通信&#xff0c…

鸿蒙轻内核A核源码分析系列四(2) 虚拟内存

本文我们来熟悉下OpenHarmony鸿蒙轻内核提供的虚拟内存&#xff08;Virtual memory&#xff09;管理模块。 本文中所涉及的源码&#xff0c;以OpenHarmony LiteOS-A内核为例&#xff0c;均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板…