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

文章目录

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React Redux

React Redux是Redux的官方React UI绑定层。它允许您的React组件从Redux存储读取数据&#xff0c;并将操作分派到存储以更新状态。redux是一个管理状态数据state的容器。提供了可预测的状态管理。 React Redux 8.x需要React 16.8.3或更高版本/Rect Native 0.59或更高&#xff0c…

萌啦OZON数据分析工具:OZON电商卖家的得力助手

在当下电商领域&#xff0c;数据分析的重要性不言而喻。对于在OZON这一俄罗斯电商平台上耕耘的卖家而言&#xff0c;拥有一款高效、准确的数据分析工具&#xff0c;无疑是提升销售业绩、优化运营策略的关键。今天&#xff0c;我们就来聊聊“萌啦OZON数据分析工具”&#xff0c;…

每日一练——反转链表

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head) {if (NULL head)return head;struct ListNode*…

从0到100:找搭子小程序开发笔记(一)

背景调查 “找搭子”小程序&#xff1a;能够解决人们在社交、休闲和约会方面的需求&#xff0c;提供方便快捷的方式来找到合适的伴侣或活动伙伴。许多人在社交场合中感到焦虑或不安&#xff0c;因此他们更倾向于使用在线平台来认识新的朋友或搭子。有些人可能生活在一个较小或…

LayerNorm层归一化

1.背景 与 Batch normalization 不同&#xff0c;Layer normalization 是在特征维度上进行标准化的&#xff0c;而不是在数据批次维度上。像 Batch Norm 它的核心是数据批次之间的归一化【强调的是第 i 批次和第 i1 批次的区别&#xff0c;然后BN去缩小他们的的区别】&#xf…

opencv_GUI

图像入门 import numpy as np import cv2 as cv # 用灰度模式加载图像 img cv.imread(C:/Users/HP/Downloads/basketball.png, 0)# 即使图像路径错误&#xff0c;它也不会抛出任何错误&#xff0c;但是打印 img会给你Nonecv.imshow(image, img) cv.waitKey(5000) # 一个键盘绑…

JAVAEE值之网络原理(1)_传输控制协议(UDP)、概念、特点、结构、代码实例

前言 在前两节中我们介绍了UDP数据报套接字编程&#xff0c;但是并没有对UDP进行详细介绍&#xff0c;本节中我们将会详细介绍传输层中的UDP协议。 一、什么是UDP&#xff1f; UDP工作在传输层&#xff0c;用于程序之间传输数据的。数据一般包含&#xff1a;文件类型&#xff0…

掌握Google搜索结果获取

在数据驱动的决策世界中&#xff0c;获取准确而全面的信息至关重要。Google 搜索结果抓取是一种强大的技术&#xff0c;可以让企业、调查人员和研究人员从搜索引擎结果中提取可靠的数据。本综合指南将深入研究 Google 搜索结果的最佳实践、工具和道德考量&#xff0c;以确定能够…

攻防演练之-网络安全产品大巡礼二

书接上文&#xff0c;《网络安全攻防演练风云》专栏之攻防演练之-网络安全产品大巡礼一&#xff0c;这里。 “咱们中场休息一会&#xff0c;我去接杯水哈”&#xff0c;看着认真听讲的众人&#xff0c;王工很是满意&#xff0c;经常夹在甲乙两方受气的他&#xff0c;这次终于表…

流批一体计算引擎-9-[Flink]中的数量窗与时间窗

1 数量窗 1.1 数量滚动窗口 0基础学习PyFlink——个数滚动窗口(Tumbling Count Windows) 1.1.1 代码分析 Tumbling Count Windows是指按元素个数计数的滚动窗口。 滚动窗口是指没有元素重叠的窗口。 (1)构造了一个KeyedStream&#xff0c;用于存储word_count_data中的数据。…

2025年QS世界大学排名,美国大学表现如何?

大多数访问学者申请&#xff0c;在探讨QS大学排名中美国大学的表现时&#xff0c;我们不难发现这些学府在全球高等教育舞台上占据着举足轻重的地位。QS排名作为评估全球大学综合实力的重要指标之一&#xff0c;充分展示了美国大学在学术声誉、科研实力、教学质量和国际影响力等…

专属部署的优势和企业价值

纷享销客支持多种部署方式&#xff0c;满足不同企业在高性能、隔离性、安全性、合规性等方面的要求。 公有云SaaS 公有云SaaS服务即直接使用纷享云服务&#xff0c;CRM应用、数据等均在纷享云&#xff0c;客户只需开通账号和相关服务&#xff0c;做到了即开即用。 纷享云采用…

Error:Kotlin: Module was compiled with an incompatible version of Kotlin.

一、问题&#xff1a;运行spring boot项目时&#xff0c;idea报出错误&#xff1a;时提示报错如下图&#xff1a; 错误代码&#xff1a; Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected …

springboot p2p金融信贷平台的设计与实现-计算机毕业设计源码82978

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对p2p金融信贷平台等问题&#xff0c;对p2p金…

PDF编辑与修正 提高工作效率 Enfocus PitStop Pro 2022 中文

Enfocus PitStop Pro 2022是一款专为Mac用户设计的强大PDF编辑和校对工具。它支持添加、删除、合并、分割PDF页面&#xff0c;以及文本和图像的编辑&#xff0c;如文字替换、字体更改、颜色调整等。内置自动修复功能&#xff0c;能快速检测并修复缺失字体、重叠文本等常见问题。…

健身小程序:智能化助力个人健身旅程

一、智能化功能的核心 健身小程序的智能化功能主要体现在以下几个方面&#xff1a; 智能健身计划推荐&#xff1a;小程序内置了先进的算法&#xff0c;能够根据用户的身体状况、健身目标和时间安排&#xff0c;智能推荐个性化的健身计划。这些计划不仅科学合理&#xff0c;而且…

在Vue2和Vue3中ECharts如何使用,详细步骤,ref,$ref。echarts官网。

不管是在vue2中还是在vue3中其实本质上的原理和步骤都是一样的&#xff0c;只是语法可能有所不同。 为了方便大家看起乱&#xff0c;vue2和vue3我分开写。 echarts官网&#xff1a; https://echarts.apache.org/zh/index.html Vue2篇&#xff1a; 1.导入echarts包&#xf…

云联HIS系统源码,二级医院信息系统源码,支持云架构部署模式

采用java语言开发B/S广域互联模式&#xff0c;支持云架构部署模式&#xff0c;支持大数据分析技术&#xff1b;支持与医保平台接口、电子票据对接。 云HIS系统相关技术&#xff1a; 后台&#xff1a;JavaSpring&#xff0c;SpringBoot&#xff0c;SpringMVC&#xff0c;Sprin…

数学模型:操作系统中FCFS、SJF、HRRN算法的平均周转时间比较 c语言

摘 要 研究目的&#xff1a;比较操作系统中进程调度FCFS、SJF、HRRN算法的平均周转时间和带权周转时间的大小关系。 研究方法&#xff1a;在建模分析时&#xff0c;分别举4个进程的例子&#xff0c;1个进程用两个字母分别表示到达时间和执行时间。分两种极端情况&#xff0c…

解锁工业数据流:NeuronEX 规则调试功能实操指南

工业企业要实现数据驱动的新质生产力升级&#xff0c;一个重要的环节便是如何准确、可靠地收集并利用生产过程中的数据流。 NeuronEX 工业边缘软件中的规则调试功能&#xff0c;可帮助用户在安全的环境中模拟数据输入&#xff0c;测试和优化数据处理规则&#xff0c;从而提前发…