当前位置: 首页 > news >正文

SpringBoot 搭建sftp服务 实现远程上传和下载文件

maven依赖:

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

application.yml

sftp:protocol: sftphost: port: 22username: rootpassword: spring:servlet:multipart:max-file-size: 500MBmax-request-size: 500MB

注:springboot自带的tomcat会限制上传文件的大小,需要在yml文件里手动设置max-file-size

SftpProperties.java

@Data
@Component
@ConfigurationProperties(prefix = "sftp")
public class SftpProperties {private String host;private int port;private String username;private String password;private String protocol;
}

SftpUtils.java

@Slf4j
@Component
public class SftpUtils {@Resourceprivate SftpProperties sftpProperties;public ChannelSftp createSftp() throws JSchException {JSch jsch = new JSch();log.info("Try to connect sftp[" + sftpProperties.getUsername() + "@" + sftpProperties.getHost() + "]");Session session = createSession(jsch, sftpProperties.getHost(), sftpProperties.getUsername(), sftpProperties.getPort());session.setPassword(sftpProperties.getPassword());session.setConfig("StrictHostKeyChecking", "no");session.connect();log.info("Session connected to {}.", sftpProperties.getHost());Channel channel = session.openChannel(sftpProperties.getProtocol());channel.connect();log.info("Channel created to {}.", sftpProperties.getHost());return (ChannelSftp) channel;}public Session createSession(JSch jsch, String host, String username, Integer port) throws JSchException {Session session = null;if (port <= 0) {session = jsch.getSession(username, host);} else {session = jsch.getSession(username, host, port);}if (session == null) {throw new RuntimeException(host + "session is null");}return session;}public void disconnect(ChannelSftp sftp) {try {if (sftp != null) {if (sftp.isConnected()) {sftp.disconnect();} else if (sftp.isClosed()) {log.error("sftp 连接已关闭");}if (sftp.getSession() != null) {sftp.getSession().disconnect();}}} catch (JSchException e) {log.error("sftp 断开连接失败,原因:{}", e.getMessage(), e);}}
}

SftpController.java

@RestController
public class SftpController {@Autowiredprivate SftpService sftpService;@PostMapping("/upload")public void upload(String remotePath, MultipartFile file) {sftpService.upload(remotePath, file);}@GetMapping("/download")public void download(String remotePath, String localPath) {sftpService.download(remotePath, localPath);}
}

SftpServiceImpl.java

@Service
@Slf4j
public class SftpServiceImpl implements SftpService {@Autowiredprivate SftpUtils sftpUtils;@Overridepublic void upload(String remotePath, MultipartFile file) {ChannelSftp sftp = null;try {// 开启sftp连接sftp = sftpUtils.createSftp();sftp.cd(remotePath);log.info("修改目录为:{}", remotePath);// 上传文件sftp.put(file.getInputStream(), file.getOriginalFilename());log.info("上传文件成功,目标目录:{}", remotePath);} catch (Exception e) {log.error("上传文件失败,原因:{}", e.getMessage(), e);throw new RuntimeException("上传文件失败");} finally {// 关闭sftpsftpUtils.disconnect(sftp);}}@Overridepublic void download(String remotePath, String localPath) {ChannelSftp sftp = null;OutputStream outputStream = null;try {sftp = sftpUtils.createSftp();String path = remotePath.substring(0, remotePath.lastIndexOf("/"));String fileName = remotePath.substring(remotePath.lastIndexOf("/") + 1);System.out.println("path:" + path);System.out.println("fileName:" + fileName);sftp.cd(path);if(isFileExist(remotePath, sftp)) { //如果远程文件存在File localFile = new File(localPath);if(!localFile.exists()) { //如果本地目录不存在,则创建目录localFile.mkdirs();}outputStream = new FileOutputStream(new File(localPath + "/" + fileName));sftp.get(fileName, outputStream);log.info("下载文件成功");} else {log.error("远程文件不存在");throw new RuntimeException("远程文件不存在");}} catch (Exception e) {log.error("sftp文件下载失败,目标文件名:{},原因:{}", remotePath, e.getMessage(), e);throw new RuntimeException("远程文件下载失败");} finally {// 关闭sftpsftpUtils.disconnect(sftp);}}//判断文件是否存在private boolean isFileExist(String remotePath, ChannelSftp sftp) {try {SftpATTRS lstat = sftp.lstat(remotePath);return lstat != null;} catch (Exception e) {log.error("判断文件是否存在失败,原因:{}", e.getMessage(), e);return false;}}
}

接口测试:

上传接口:
请添加图片描述
下载接口:
请添加图片描述

相关文章:

SpringBoot 搭建sftp服务 实现远程上传和下载文件

maven依赖&#xff1a; <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version> </dependency>application.yml sftp:protocol: sftphost: port: 22username: rootpassword: sp…...

IDEA中使用leetcode 刷题

目录 1.IDEA下载leetcode插件 2.侧边点开插件 3.打开网页版登录找到cookie复制 4.回到IDEA登录 5.刷题 6.共勉 1.IDEA下载leetcode插件 2.侧边点开插件 3.打开网页版登录找到cookie复制 4.回到IDEA登录 5.刷题 6.共勉 算法题来了不畏惧&#xff0c; 挑战前行是成长的舞台…...

华为海思CPU解读

安全可靠CPU测评结果&#xff08;华为海思篇&#xff09; 中国信息安全测评中心于2024年5月20日发布安全可靠测评结果公告&#xff08;2024年第1号&#xff09;&#xff0c;公布依据《安全可靠测评工作指南&#xff08;试行&#xff09;》的测评结果&#xff0c;自发布起有效期…...

中介子方程三十三

XXFXXuXXWXXuXXdXXrXXαXXuXpXXdXXpXuXXαXXrXXdXXuXWXπXXWXeXyXeXbXπXpXXNXXqXeXXrXXαXXuXpXXdXXpXuXXαXXrXXeXqXXNXXpXπXbXeXyXeXWXXπXWXuXXdXXrXXαXXuXpXXdXXpXuXXαXXrXXdXXuXXWXXuXXFXXEXXyXXEXXrXXαXXuXpXXdXXpXuXXαXXrXXEXXyXXαXiXXαXiXrXkXtXyXXpXVXXdXuXWX…...

今年哪两个行业可能有贝塔?

银行和综合板块存在比较明显的行业贝塔&#xff0c;背后原因是&#xff1a;银行板块中&#xff0c;最小的几家银行市值也不小&#xff1b;综合板块中&#xff0c;最大的几家市值也不大。 一、今年哪两个行业可能有贝塔&#xff1f; 我们一直强调今年市场呈现出【行业弱beta、风…...

嵌入式软件开发工具使用介绍

软件开发工具 辅助开发工具 硬件工具与仪器设备 逻辑分析仪使用 串口数据解码分析 示波器使用 1.示波器简介 TBS 1052B&#xff08;Tektronix&#xff09;系列数字存储示波器在紧凑的设计中提供了经济的性能。 由于多种标配功能&#xff0c; 包括 USB 连接、34 种自动测量、…...

【TB作品】MSP430G2553,单片机,口袋板, 交通灯控制系统

题8 交通灯控制系统 十字路口交通灯由红、绿两色LED显示器&#xff08;两位8段LED显示器&#xff09;组成&#xff0c;LED显示器显示切换倒计时&#xff0c;以秒为单位&#xff0c;每秒更新一次&#xff1b;为确保安全&#xff0c;绿LED计数到0转红&#xff0c;经5秒延时&#…...

windows 安装 Kubernetes(k8s)

windows 安装 docker 详情见&#xff1a; https://blog.csdn.net/sinat_32502451/article/details/133026301 minikube Minikube 是一种轻量级的Kubernetes 实现&#xff0c;可在本地计算机上创建VM 并部署仅包含一个节点的简单集群。 下载地址&#xff1a;https://github.…...

C语言 | Leetcode C语言题解之第189题轮转数组

题目&#xff1a; 题解&#xff1a; void swap(int* a, int* b) {int t *a;*a *b, *b t; }void reverse(int* nums, int start, int end) {while (start < end) {swap(&nums[start], &nums[end]);start 1;end - 1;} }void rotate(int* nums, int numsSize, int…...

【安全审核】音视频审核开通以及计费相关

融云控制台音视频审核入口&#xff1a;音视频审核 1 音视频审核文档&#xff1a;融云开发者文档 1 提示&#xff1a; 开发环境&#xff1a; 免费体验 7 天&#xff08;含 21 万分钟音频流和 420 万张视频审核用量&#xff09;&#xff0c;免费额度用尽后&#xff0c;将关停服务…...

【实战】Spring Cloud Stream 3.1+整合Kafka

文章目录 前言新版版本优势实战演示增加maven依赖增加applicaiton.yaml配置新增Kafka通道消费者新增发送消息的接口 实战测试postman发送一个正常的消息postman发送异常消息 前言 之前我们已经整合过Spring Cloud Stream 3.0版本与Kafka、RabbitMQ中间件&#xff0c;简直不要太…...

java之可变字符串之append方法

可变字符串如果要添加内容&#xff0c;需要用到append方法 语法格式如下 sbf.append(obj) 其中sbf是任意的可变字符串 obj是任意数据类型的对象 这个方法是将任意数据转换成字符串&#xff0c;然后添加到此序列中 public class Buffer {public static void main(String[]…...

[保姆级教程]uniapp自定义导航栏

文章目录 导文隐藏默认导航栏&#xff1a;全局隐藏当前页面隐藏 添加自定义导航栏视图&#xff1a;手写导航栏组件导航栏 导文 在 UniApp 中&#xff0c;自定义导航栏通常涉及到隐藏默认的导航栏&#xff0c;并在页面顶部添加自定义的视图组件来模拟导航栏的功能。 隐藏默认导航…...

项目训练营第二天

项目训练营第二天 用户登录逻辑 1、账户名不少于4位 2、密码不少于8位 3、数据库表中能够查询到账户、密码 4、密码查询时用同样加密脱敏处理手段处理后再和数据库中取出字段进行对比&#xff0c;如果账户名未查询到&#xff0c;直接返回null 5、后端设置相应的脱敏后用户的s…...

考研数学一有多难?130+背后的残酷真相

考研数学一很难 大家平时在网上上看到很多人说自己考了130&#xff0c;其实这些人只占参加考研数学人数的极少部分&#xff0c;有个数据可以展示出来考研数学到底有多难&#xff1a; 在几百万考研大军中&#xff0c;能考到120分以上的考生只有2%。绝大多数人的分数集中在30到…...

vue2脚手架笔记总结1

1.什么是组件 组件是实现局部代码和功能资源的集合 2.vue.config.js配置文件 使用vue inspect > output.js可以查看到Vue脚手架的默认配置,但是在这里面修改不会影响实际的配置&#xff0c;如果需要修改配置需要使用用vue.config.js文件&#xff0c;详情见:https://cli.vuej…...

校园巡礼:一周只上四天课,入学即发钱?深圳理工大学,开局即王炸

校园巡礼 | 一周只上四天课&#xff0c;入学即发钱&#xff1f;深圳理工大学&#xff0c;开局即王炸&#xff01; 会议之眼 快讯 目前各省的高考成绩现已陆续揭晓&#xff0c;广东省教育考试院发布了2024年高考录取最低分数线&#xff0c;物理类本科线为442分&#xff0c;历史…...

免交互 实验

免交互 交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的&#xff0c;通过第三方的方式把指令传送给程序&#xff0c;不用直接下达指令。 Here document 免交互 这是命令行格式&#…...

Sublime Text 设置

备份 {"font_size": 10,"index_files": true,"font_face": "Courier New","vintage_start_in_command_mode": false,"ignored_packages": ["Vintage"],"word_wrap": "false" }关闭…...

spire.Pdf 将pdf转成image

一、nuget安装 <ItemGroup><PackageReference Include"Spire.PDF" Version"10.6.7" /></ItemGroup> 二、直接上代码 using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.IO;namespace …...

DriveBench:面向真实驾驶场景的长序列多智能体交互基准测试框架

1. 项目概述&#xff1a;从“世界基准”到“驾驶基准”的演进如果你在自动驾驶或者计算机视觉领域摸爬滚打过几年&#xff0c;一定对“基准测试”&#xff08;Benchmark&#xff09;这个词又爱又恨。爱的是&#xff0c;它提供了一个相对公平的擂台&#xff0c;让不同算法、不同…...

Nestia:基于TypeScript编译时分析的NestJS端到端类型安全实践

1. 项目概述&#xff1a;当NestJS遇上TypeScript的极致类型安全如果你正在用NestJS开发后端API&#xff0c;并且对TypeScript的类型安全有近乎偏执的追求&#xff0c;那么你很可能已经听说过&#xff0c;或者正在寻找一个能让你“写一次&#xff0c;安全两次”的工具。我说的“…...

fold命令行工具:高效文本数据聚合与分析的瑞士军刀

1. 项目概述&#xff1a;一个为“折叠”而生的高效工具 最近在折腾一些数据处理和文件整理的工作流时&#xff0c;我一直在寻找一个能让我“折叠”起来思考的工具。我说的“折叠”&#xff0c;不是物理上的&#xff0c;而是逻辑上的——把复杂的、多维度的信息&#xff0c;按照…...

ARM Cortex-X4/X925处理器仿真模型与指令集详解

1. ARM Cortex-X4/X925处理器仿真模型概述处理器仿真模型在现代芯片设计中扮演着至关重要的角色&#xff0c;特别是在Arm架构的生态系统中。作为Arm最新一代高性能核心&#xff0c;Cortex-X4和X925的Iris仿真组件提供了完整的指令集和微架构行为建模&#xff0c;使开发者能够在…...

开源婚礼技能库:用项目管理思维破解备婚焦虑,打造个性化高性价比婚礼

1. 项目概述&#xff1a;婚礼技能库的诞生与价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“awesome-wedding-skills”。光看名字&#xff0c;你可能会觉得这又是一个普通的“awesome”系列资源列表&#xff0c;无非是收集一些婚礼策划、摄影、化妆的链接。但当我点…...

旁遮普语内容出海迫在眉睫!ElevenLabs+AWS Polly双引擎容灾方案(含Failover切换SLA 99.99%保障协议模板)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;旁遮普语内容出海的战略紧迫性与本地化语音缺口 旁遮普语是全球使用人数超1.2亿的语言&#xff0c;主要分布在印度旁遮普邦、巴基斯坦旁遮普省及庞大的海外侨民社群&#xff08;如加拿大、英国、美国&…...

【仿真学习框架】MultiModalWBC 完全指南:从入门到精通的多模态全身控制框架

版本: v1.0 | 日期: 2026-05-15 目标读者: 具身智能研究者、机器人学习工程师、人形机器人开发者 前置知识: 基础强化学习(PPO)、PyTorch、刚体动力学概念 📑 目录 1. 初见 MultiModalWBC:我们到底在解决什么问题? 1.1 人形机器人控制的"碎片化"困境 1.2 多模态…...

Noto Emoji字体架构深度解析:现代表情符号渲染的技术实现与性能优化

Noto Emoji字体架构深度解析&#xff1a;现代表情符号渲染的技术实现与性能优化 【免费下载链接】noto-emoji Noto Emoji fonts 项目地址: https://gitcode.com/gh_mirrors/no/noto-emoji Noto Emoji作为Google开源的表情符号字体库&#xff0c;提供了跨平台的Unicode表…...

基于Databerry的私有数据AI应用构建:从RAG原理到生产部署

1. 项目概述&#xff1a;一个开箱即用的AI应用构建平台如果你正在寻找一个能快速将私有数据&#xff08;比如公司文档、个人笔记、产品手册&#xff09;转化为智能问答机器人的工具&#xff0c;但又不想从零开始折腾复杂的向量数据库、嵌入模型和API集成&#xff0c;那么gmpetr…...

ncmdump终极指南:如何快速免费解锁网易云音乐NCM格式

ncmdump终极指南&#xff1a;如何快速免费解锁网易云音乐NCM格式 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的加密文件无法在其他设备播放而烦恼吗&#xff1f;ncmdump正是你需要的解决方案&#xff01;这…...