Java 项目如何连接并使用 SFTP 服务的示例详解

devtools/2024/10/18 11:53:54/

文章目录

    • 1、SFTP介绍
    • 2、pom依赖
    • 3、SFTPUtil
    • 4、测试
    • 5、测试结果

1、SFTP介绍

SFTP(Secure File Transfer Protocol)是一种安全的文件传输协议,是SSH(Secure Shell)协议的一个子协议,设计用于加密和保护文件传输的安全性。SSH本身是一种网络协议,用于在不安全的网络中提供安全的远程登录和其他安全网络服务。SFTP则在此基础上,专注于文件的安全传输。

  • 加密传输:SFTP使用加密来保护传输的数据,包括文件内容和认证信息。
  • 身份验证:SFTP使用SSH身份验证机制来验证用户身份。用户通常需要提供用户名和密码,或者使用SSH密钥对进行身份验证。
  • 文件和目录操作:SFTP支持文件和目录的上传、下载、删除、重命名和创建等操作。
  • 跨平台兼容性:SFTP是一个跨平台协议,可以在各种操作系统上使用,包括Linux、Unix、Windows等。
  • 端到端数据完整性:SFTP确保传输的文件在源和目标之间的完整性,防止数据在传输过程中被篡改或损坏。
  • 可扩展性:SFTP可以与其他协议和安全机制一起使用,以增强其功能。例如,它可以与公钥基础设施(PKI)一起使用以实现更高级的安全性。

SFTP通常用于许多场景,包括远程服务器维护、备份、文件共享和在不同计算机之间传输敏感数据。由于它提供了强大的安全性,因此特别适用于传输金融账户、公司文件和政府数据等敏感信息。

  • 端口:SFTP的默认端口与SSH相同,为22。这意味着只要sshd服务器启动了,SFTP就可使用,不需要额外安装。
  • 守护进程:SFTP本身没有单独的守护进程,它必须使用SSHD守护进程(端口号默认是22)来完成相应的连接操作。
  • 配置:SFTP的配置通常与SSH配置相关。例如,可以通过修改SSH配置文件(如sshd_config)来启用或禁用SFTP功能,以及设置相关的访问权限和安全策略。

SFTP结合了SSH的安全性和文件传输的便捷性,成为许多组织和个人在传输敏感数据时的首选协议。

2、pom依赖

SFTP需要第三方依赖进行连接。

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

3、SFTPUtil

java">package com.wen.util;import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;/*** @author : rjw* @date : 2024-10-14*/
public class SFTPUtil {private static final Logger logger = LoggerFactory.getLogger(SFTPUtil.class);private Session session;private ChannelSftp channelSftp;/*** 登录*/public boolean login(String hostname, int port, String username, String password) {try {JSch jSch = new JSch();// 根据用户名,IP地址获取一个session对象。session = jSch.getSession(username, hostname, port);session.setPassword(password);// 避免第一次连接时需要输入yes确认Properties config = new Properties();config.put("StrictHostKeyChecking", "no");session.setConfig(config);session.connect();logger.info("成功连接服务器");channelSftp = (ChannelSftp) session.openChannel("sftp");channelSftp.connect();logger.info("成功连接服务器");return true;} catch (JSchException e) {logger.error("SFTPUtil login file error:", e);}return false;}/*** 退出*/public void logout() {if (channelSftp != null && channelSftp.isConnected()) {try {channelSftp.disconnect();logger.info("成功退出 SFTP 服务器");} catch (Exception e) {logger.error("退出SFTP服务器异常: ", e);} finally {try {channelSftp.disconnect(); // 关闭FTP服务器的连接} catch (Exception e) {logger.error("关闭SFTP服务器的连接异常: ", e);}}}if (session != null && session.isConnected()) {try {session.disconnect();logger.info("成功退出 session 会话");} catch (Exception e) {logger.error("退出 session 会话异常: ", e);} finally {try {session.disconnect(); // 关闭FTP服务器的连接} catch (Exception e) {logger.error("关闭 session 会话的连接异常: ", e);}}}}/*** 判断是否连接*/public boolean isConnected() {return channelSftp != null && channelSftp.isConnected();}/*** 上传文件* 采用默认的传输模式:OVERWRITE** @param src 输入流(文件)* @param dst 上传路径* @param fileName 上传文件名* @throws SftpException*/public boolean upLoadFile(InputStream src, String dst, String fileName) throws SftpException {boolean isSuccess = false;try {if (createDir(dst)) {channelSftp.put(src, fileName);isSuccess = true;}} catch (SftpException e) {logger.error(fileName + "文件上传异常", e);}return isSuccess;}/*** 创建一个文件目录** @param createPath 路径* @return*/public boolean createDir(String createPath) {boolean isSuccess = false;try {if (isDirExist(createPath)) {channelSftp.cd(createPath);return true;}String[] pathArray = createPath.split("/");StringBuilder filePath = new StringBuilder("/");for (String path : pathArray) {if (path.isEmpty()) {continue;}filePath.append(path).append("/");if (isDirExist(filePath.toString())) {channelSftp.cd(filePath.toString());} else {// 建立目录channelSftp.mkdir(filePath.toString());// 进入并设置为当前目录channelSftp.cd(filePath.toString());}}channelSftp.cd(createPath);isSuccess = true;} catch (SftpException e) {logger.error("目录创建异常!", e);}return isSuccess;}/*** 判断目录是否存在** @param directory 路径* @return*/public boolean isDirExist(String directory) {boolean isSuccess = false;try {SftpATTRS sftpATTRS = channelSftp.lstat(directory);isSuccess = true;return sftpATTRS.isDir();} catch (Exception e) {logger.info("SFTPUtil path has error:{}", directory);logger.error("SFTPUtil path has error: ", e);if (e.getMessage().equalsIgnoreCase("no such file")) {isSuccess = false;}}return isSuccess;}/*** 重命名指定文件或目录*/public boolean rename(String oldPath, String newPath) {boolean isSuccess = false;try {channelSftp.rename(oldPath, newPath);isSuccess = true;} catch (SftpException e) {logger.error("重命名指定文件或目录异常", e);}return isSuccess;}/*** 列出指定目录下的所有文件和子目录。*/public Vector ls(String path) {try {Vector vector = channelSftp.ls(path);return vector;} catch (SftpException e) {logger.error("列出指定目录下的所有文件和子目录。", e);}return null;}/*** 删除文件*/public boolean deleteFile(String directory, String deleteFile) {boolean isSuccess = false;try {channelSftp.cd(directory);channelSftp.rm(deleteFile);isSuccess = true;} catch (SftpException e) {logger.error("删除文件失败", e);}return isSuccess;}/*** 下载文件** @param directory 下载目录* @param downloadFile 下载的文件* @param saveFile 下载到本地路径*/public boolean download(String directory, String downloadFile, String saveFile) {boolean isSuccess = false;try {channelSftp.cd(directory);File file = new File(saveFile);channelSftp.get(downloadFile, new FileOutputStream(file));isSuccess = true;} catch (SftpException e) {logger.error("下载文件失败", e);} catch (FileNotFoundException e) {logger.error("下载文件失败", e);}return isSuccess;}/*** 输出指定文件流*/public InputStream getFile(String path) {try {InputStream inputStream = channelSftp.get(path);return inputStream;} catch (SftpException e) {throw new RuntimeException(e);}}/*** 下载文件,新*/public InputStream downloadFile(String remoteFileName, String remoteFilePath) {InputStream input = null;try {if (!isDirExist(remoteFilePath)) {logger.info("SFTPUtil not changeWorkingDirectory.filename:{},Path:{}", remoteFileName, remoteFilePath);logout();return input;}logger.info("SFTPUtil Info filename:{},Path:{}", remoteFileName, remoteFilePath);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();input = new ByteArrayInputStream(outputStream.toByteArray());outputStream.close();logger.info("file download. filename:{},Path:{}", remoteFileName, remoteFilePath);} catch (Exception e) {logger.error("SFTPUtil download file error:", e);logout();}return input;}/*** 验证sftp文件是否有效(判断文件属性的日期)*/public String validateSourceData(String fileName, String remoteFilePath, Date nowTime) throws IOException, SftpException {Date temp = null;if (!isDirExist(remoteFilePath)) {logout();return "尝试切换SFTP路径失败, 文件路径: " + remoteFilePath + fileName;}Vector vector = channelSftp.ls(remoteFilePath);for (int i = 0; i < vector.capacity(); i++) {ChannelSftp.LsEntry data = (ChannelSftp.LsEntry) vector.get(i);if (data.getFilename().equalsIgnoreCase(fileName)) {temp = new Date(data.getAttrs().getMTime() * 1000L);//logger.info("时间: timeStamp:{},nowTime:{}",temp,nowTime);if (temp.getTime() == nowTime.getTime()) {return "SFTP文件没有更新";}nowTime.setTime(temp.getTime());break;}}//logout();return null;}/*** IP*/public String getSFTPHost() {return session.getHost();}/*** 端口*/public int getSFTPPort() {return session.getPort();}
}

4、测试

java">public class Test {private static SFTPUtil sftpUtil = new SFTPUtil();public static String convertInputStreamToString(InputStream inputStream) throws IOException{StringBuilder stringBuilder = new StringBuilder();try{BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));String line;while ((line = bufferedReader.readLine()) != null){System.out.println(line);stringBuilder.append(line).append("\n");}}catch (Exception e){System.out.println(e);}if(stringBuilder.length() > 0 && stringBuilder.charAt(stringBuilder.length() - 1) == '\n'){stringBuilder.setLength(stringBuilder.length() - 1);}return stringBuilder.toString();}public static void main(String[] args) {boolean connected = sftpUtil.isConnected();if (!connected) {System.out.println("连接SFTP");// 折里可以采用配置文件 @Value 注解connected = sftpUtil.login("10.26.73.163", 2222, "username", "password");}if (connected) {System.out.println("连接成功");System.out.println(sftpUtil.getSFTPHost() + " : " + sftpUtil.getSFTPPort());InputStream inputStream = sftpUtil.getFile("/rjw/wind.txt");String s = convertInputStreamToString(inputStream);System.out.println(s);File file = new File("C:\\Users\\wen\\Desktop\\sun.txt");InputStream inputStream1 = Files.newInputStream(file.toPath());boolean dir = sftpUtil.upLoadFile(inputStream1, "/rjw", "big.txt");System.out.println("添加文件成功: " + dir);sftpUtil.logout();}}
}

5、测试结果

SFTP测试结果


http://www.ppmy.cn/devtools/126715.html

相关文章

【Java知识】Java进阶-线程池深度解读

文章目录 线程池概述线程池的核心组件和概念&#xff1a;线程池的工作原理&#xff1a;线程池的创建&#xff1a;线程池的关闭&#xff1a;总结&#xff1a; 线程池种类以及用途以ScheduledThreadPool为例的类继承关系 拒绝策略有哪些&#xff1f;使用范例固定大小的线程池单线…

SAP SD学习笔记- 豆知识 - SAP中的英文 - SD中英文,日语,中文

SD的中部分中日英文对照。先收集&#xff0c;等以后再整理。 1&#xff0c;販売管理&#xff08;销售管理&#xff09; 日本語英語中国語受注伝票sales order销售订单出荷伝票delivery order交货订单ピッキングリストpicking list领货清单シップメント伝票shipment document发…

十一、结构型(享元模式)

享元模式&#xff08;Flyweight Pattern&#xff09; 概念 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过共享大量细粒度对象来减少内存占用。享元模式将内外部状态分离&#xff0c;内部状态可以共享&#xff0c;外部状态由客户端…

数据字典是什么?和数据库、数据仓库有什么关系?

一、数据字典的定义及作用 数据字典是一种对数据的定义和描述的集合&#xff0c;它包含了数据的名称、类型、长度、取值范围、业务含义、数据来源等详细信息。 数据字典的主要作用如下&#xff1a; 1. 对于数据开发者来说&#xff0c;数据字典包含了关于数据结构和内容的清晰…

FreeRTOS - 队列

在学习FreeRTOS过程中&#xff0c;结合韦东山-FreeRTOS手册和视频、野火-FreeRTOS内核实现与应用开发、及网上查找的其他资源&#xff0c;整理了该篇文章。如有内容理解不正确之处&#xff0c;欢迎大家指出&#xff0c;共同进步。 1. 队列 1.1 队列基本概念 队列(queue)可以用…

UNIX网络编程-简介

概述 要编写通过计算机网络通信的程序&#xff0c;首先要确定这些程序相互通信所用的协议&#xff08;protocal&#xff09;。 大多数网络应用划分为客户端&#xff08;client&#xff09;和服务器&#xff08;server&#xff09;。在设计网络应用时&#xff0c;确定总是由客户…

线性代数 行列式

一、行列式 1、定义 一个数学概念&#xff0c;主要用于 线性代数中&#xff0c;它是一个可以从方阵&#xff08;即行数和列数相等的矩阵&#xff09;形成的一个标量&#xff08;即一个单一的数值&#xff09; 2、二阶行列式 &#xff0c;像这样将一个式子收缩称为一个 2*2 的…

2d 数字人实时语音聊天对话使用案例;支持asr、llm、tts实时语音交互

参考: https://github.com/lyz1810/live2dSpeek 下载live2dSpeek项目 ## 下载live2dSpeek git clone https://github.com/lyz1810/live2dSpeek cd live2dSpeek-main ## 运行live2dSpeek npm install -g http-server http-server .更改新的index.html页面 index.html