Springboot使用Sftp实现服务器文件上传下载

SpringBoot2.2+commons-pool2实现多Ftp连接池完整项目,开箱即用,经过长期生产使用稳定可靠 阅读详情

提示:文章如有错误的地方请指出,以免误人子弟!


提示:以下是本篇文章正文内容,下面案例可供参考

一、导入maven jar包

maven 地址

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

二、上代码

  1. application.yml (根据自己业务来添加路径地址,用不上的可以删掉,我这里就不删了)
sftp:
  # 服务器地址
  host: 192.168.96.135
  # 端口
  port: 22
  # 账号
  userName: root
  # 密码
  password: wang521
  # 图片的根路径
  basePath: /home/nginx/image
  # 音频的根路径
  audioPath: /home/nginx/audio
  # 视频的根路径
  videoPath: /home/nginx/video
  # channel连接超时时间
  timeout: 30000
  #连接次数
  count: 10
  #休眠时间
  sleepTime: 6000
  #服务器头像地址
  titleImgsPath: http://192.168.96.135:80/image/
  #服务器音频地址
  titleAudiosPath: http://192.168.96.135:80/audio/
  #服务器视频地址
  titleVideosPath: http://192.168.96.135:80/video/
  1. 新建一个实体类,用起来方便的
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

import java.io.Serializable;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 17:59
 */
@Data
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class SftpDTO implements Serializable {
    /**
     * description: Ip
     */
    private String hostname;
    /**
     * description: 端口
     */
    private Integer port;
    /**
     * description: 服务器用户名
     */
    private String username;
    /**
     * description: 服务器密码
     */
    private String password;
    /**
     * description: 连接超时
     */
    private Integer timeout;
    /**
     * description: 服务器根路径
     */
    private String remoteRootPath;

	public SftpDTO() {}
    public SftpDTO(String hostname, Integer port, String username, String password, Integer timeout, String remoteRootPath) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
        this.timeout = timeout;
        this.remoteRootPath = remoteRootPath;
    }
}
  1. sftp工具类
    注意:
    这里有个地方需要注意下,单个文件或多个文件上传只需要连接一次 sftp 就好了
import com.jcraft.jsch.*;
import com.wwwh.onlyone.common.entity.userInfo.dto.SftpDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 18:17
 */
@Slf4j
@Component
@RefreshScope
public class SftpUtil
{
    /**
     * description: count-> 连接超过次数,线程休眠
     */
    @Value("${sftp.count}")
    private long count;
    /**
     * description: sleepTime-> 休眠时间
     */
    @Value("${sftp.sleepTime}")
    private long sleepTime;

    /**
     * description: count1-> 已经连接次数
     */
    private long count1 = 0;

    /**
     * description: 连接sftp服务器
     *
     * @param sftpConfig sftp实体类
     * @return com.jcraft.jsch.ChannelSftp
     * @author Mr.Tiger
     */
    public ChannelSftp connect(SftpDTO sftpConfig) {
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();
            jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort());
            Session sshSession = jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort());
            log.info("Session created ... UserName=" + sftpConfig.getUsername() + ";host=" + sftpConfig.getHostname() + ";port=" + sftpConfig.getPort());
            sshSession.setPassword(sftpConfig.getPassword());
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            log.info("Session connected ...");
            //协议
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            log.info("登录成功");
        } catch (Exception e) {
            try {
                count1 += 1;
                if (count == count1) {
                    throw new RuntimeException(e);
                }
                Thread.sleep(sleepTime);
                log.info("重新连接....");
                connect(sftpConfig);
            } catch (InterruptedException e1) {
                throw new RuntimeException(e1);
            }
        }
        return sftp;
    }

    /**
     * description: 关闭 流
     *
     * @param ins 输入流
     * @param file MultipartFile 转 File的文件
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public static void inputStreamToFile(InputStream ins,File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * description: 上传文件
     *
     * @param file 要上传的文件
     * @param directory 上传的目录
     * @param sftpConfig sftp实体类
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    public Map<String, String> upload(MultipartFile file, String directory, SftpDTO sftpConfig, String fileName) {
        Map<String, String> map = new HashMap<String, String>(10);
        ChannelSftp sftp = connect(sftpConfig);
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
                log.info("创建的路径为--:"+directory);
            } catch (SftpException e1) {
                throw new RuntimeException("ftp创建文件路径失败" + directory);
            }
        }
        InputStream inputStream = null;
        try
        {
            inputStream = file.getInputStream();
            sftp.put(inputStream, fileName);;
            map.put("code","200");
            log.info("文件头像成功");
        } catch (Exception e) {
            map.put("code","500");
            throw new RuntimeException("sftp异常" + e);
        } finally {
            disConnect(sftp);
            closeStream(inputStream,null);
        }
        return map;
    }

    /**
     * description: 上传多个文件
     *
     * @param file 要上传的文件
     * @param directory 上传的目录
     * @param sftp sftp连接对象
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    public void uploadList(MultipartFile file, String directory, ChannelSftp sftp, String fileName) {
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
                log.info("创建的路径为--:"+directory);
            } catch (SftpException e1) {
                throw new RuntimeException("ftp创建文件路径失败" + directory);
            }
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            sftp.put(inputStream, fileName);
            log.info("文件上传成功");
        } catch (Exception e) {
            throw new RuntimeException("sftp异常" + e);
        } finally {
            closeStream(inputStream,null);
        }
    }

    /**
     * description: 下载文件
     *
     * @param directory 下载目录
     * @param downloadFileUrl 下载的文件名称
     * @param sftpConfig sftp 实体类
     * @return byte[]
     * @author Mr.Tiger
     */
    public byte[] download(String directory, String downloadFileUrl, SftpDTO sftpConfig) {
        ChannelSftp sftp = connect(sftpConfig);
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            //进到文件夹下
            sftp.cd(directory);
            if (log.isInfoEnabled()) {
                log.info("打开远程文件:[{}]", new Object[]{directory});
            }
            InputStream inputStream = sftp.get(downloadFileUrl);
            byteArrayOutputStream = new ByteArrayOutputStream();
            int n = 0;
            byte[] data = new byte[1024];
            while ((n = inputStream.read(data, 0, data.length)) != -1) {
                byteArrayOutputStream.write(data, 0, n);
            }
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            if (log.isInfoEnabled()) {
                log.info("文件下载出现异常,[{}]", e);
            }
            throw new RuntimeException("文件下载出现异常,[{}]", e);
        } finally
        {
            if (byteArrayOutputStream != null)
            {
                try
                {
                    byteArrayOutputStream.flush();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            disConnect(sftp);
        }
    }

    /**
     * description: 关闭流
     *
     * @param inputStream 输入流
     * @param outputStream 输出流
     * @return void
     * @author Mr.Tiger
     */
    private void closeStream(InputStream inputStream,OutputStream outputStream) {
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(inputStream != null){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * description: 删除文件
     *
     * @param directory 要删除文件所在目录
     * @param deleteFile 要删除的文件
     * @param sftpConfig sftp实体类
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public void delete(String directory, String deleteFile, SftpDTO sftpConfig) {
        ChannelSftp sftp = null;
        try {
            sftp = connect(sftpConfig);
            sftp.cd(directory);
            sftp.rm(deleteFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally
        {
            disConnect(sftp);
        }
    }

    /**
     * description: 断掉连接
     *
     * @param sftp sftp实体类
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public void disConnect(ChannelSftp sftp) {
        try {
            sftp.disconnect();
            sftp.getSession().disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. controller 使用
    单个,多个文件上传,单个文件下载,因为本人比较懒,这里把业务代码也贴上去了没有删掉,大家用的时候把没有的业务代码删掉就好了。因为这是cloud的项目,@RefreshScope删掉,@DubboReference替换成@Autowired或者@Resource。
import com.alibaba.fastjson.JSON;
import com.jcraft.jsch.ChannelSftp;
import com.wwwh.onlyone.common.entity.userInfo.doo.SysAudios;
import com.wwwh.onlyone.common.entity.userInfo.doo.SysVideos;
import com.wwwh.onlyone.common.entity.userInfo.dto.SftpDTO;
import com.wwwh.onlyone.common.service.registry.system.SysAudiosService;
import com.wwwh.onlyone.common.service.registry.system.SysEmpInfoService;
import com.wwwh.onlyone.common.service.registry.system.SysVideosService;
import com.wwwh.onlyone.common.util.createId.SnowFlakeGenerateIdWorker;
import com.wwwh.onlyone.common.util.responseJson.ResponseResult;
import com.wwwh.onlyone.consumer.util.RedisUtil;
import com.wwwh.onlyone.consumer.util.SftpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 19:07
 */
@Slf4j
@RestController
@RequestMapping("/sftpFile")
@RefreshScope
public class SftpController
{
    private final SftpUtil sftpUtil;
    public SftpController(SftpUtil sftpUtil)
    {
        this.sftpUtil = sftpUtil;
    }

    @DubboReference
    private SysEmpInfoService sysEmpInfoService;
    @DubboReference
    private SysAudiosService sysAudiosService;
    @DubboReference
    private SysVideosService sysVideosService;

    @Autowired
    private RedisUtil redisUtil;

    @Value("${sftp.host}")
    private String host;
    @Value("${sftp.port}")
    private int port;
    @Value("${sftp.userName}")
    private String userName;
    @Value("${sftp.password}")
    private String password;
    @Value("${sftp.timeout}")
    private int timeout;
    @Value("${sftp.basePath}")
    private String basePath;
    @Value("${sftp.audioPath}")
    private String audioPath;
    @Value("${sftp.videoPath}")
    private String videoPath;
    @Value("${sftp.titleImgsPath}")
    private String titleImgsPath;
    @Value("${sftp.titleAudiosPath}")
    private String titleAudiosPath;
    @Value("${sftp.titleVideosPath}")
    private String titleVideosPath;

    /**
     * description: 上传文件
     *
     * @param file 要上传的文件
     * @param userPhone 手机号(用户标识)
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    @PostMapping("/uploads")
    public String upload(MultipartFile file, String userPhone) {
        //获取文件名称
        String filename = file.getOriginalFilename();
        String fix = null;
        if (StringUtils.isNotBlank(filename)) {
            filename = filename.replace(" ", "");
            // 获取文件名后缀
            fix = filename.substring(filename.length() - 3);;
        }

        log.info("文件后缀---:"+fix);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());
        // 雪花算法, 生成id
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker = new SnowFlakeGenerateIdWorker(0L, 0L);
        String nextId = snowFlakeGenerateIdWorker.generateNextId();
        String fileName = nextId+"."+fix;
        //个人头像全路径
        String titleImgs = titleImgsPath+format+"/"+fileName;
        log.info("头像上传-存库路径---:"+titleImgs);
        //修改用户头像
        int i = sysEmpInfoService.updateUserTitleImg(titleImgs, userPhone);
        // 更新redis 中的头像地址
        redisUtil.hset(userPhone, "headImg", titleImgs);
        Map<String, String> upload = new HashMap<String, String>();
        if(i > 0) {
            String path = basePath + "/" + format;
            log.info("上传到服务器的路径--:"+path);
            SftpDTO sftpConfig = new SftpDTO(host,port,userName,password,timeout,path);
            upload = sftpUtil.upload(file, sftpConfig.getRemoteRootPath(), sftpConfig, fileName);
        }

        //头像地址返回前端
        upload.put("imgUrl",titleImgs);
        return JSON.toJSONString(upload);
    }

    /**
     * description: 下载文件
     *
     * @param imgFileName 下载的文件名称
     * @param downloadFileName 下载目录
     * @param response response
     * @author Mr.Tiger
     */
    @PostMapping("/downLoads")
    public void downLoad(String imgFileName, String downloadFileName, HttpServletResponse response) throws UnsupportedEncodingException {
        SftpDTO sftpConfig = new SftpDTO(host,port,userName,password,timeout,basePath);
        //需要下载的服务器文件目录
        String downloadFileUrl = sftpConfig.getRemoteRootPath() + "/" + imgFileName;
        byte[] bytes = sftpUtil.download(sftpConfig.getRemoteRootPath(), downloadFileUrl, sftpConfig);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadFileName, "UTF-8"));
        byte[] buffer = new byte[1024];
        //缓存字节流
        BufferedInputStream bufferedInputStream = null;
        //输出流
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            bufferedInputStream = new BufferedInputStream(inputStream);
            int i = bufferedInputStream.read(buffer);
            while (i != -1) {
                outputStream.write(buffer, 0, i);
                i = bufferedInputStream.read(buffer);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null) {
                try {
                    outputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * description: 上传多个文件
     *
     * @param file 要上传的文件
     * @param type 文件类型
     * @param createName 上传人姓名
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    @PostMapping("/uploadList")
    public ResponseResult uploadLists(List<MultipartFile> file, Integer type, String createName)
    {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());
        SftpDTO sftpConfig = null;
        String path = null;
        List<SysAudios> sysAudiosList = null;
        List<SysVideos> sysVideosList = null;
        if (type != null) {
            // 1: 音频 2:视频
            if (type == 1) {
                path = audioPath + "/" + format;
                sysAudiosList = new ArrayList<>(file.size());
            }
            else {
                path = videoPath + "/" + format;
                sysVideosList = new ArrayList<>(file.size());
            }
            log.info("上传到服务器的路径--:"+path);
        }
        sftpConfig = new SftpDTO(host,port,userName,password,timeout,path);
        // 连接sftp
        ChannelSftp sftp = sftpUtil.connect(sftpConfig);

        if (file.size() != 0 && type != null) {
            for (MultipartFile multipartFile : file) {
                //获取文件名称
                String filename = multipartFile.getOriginalFilename();
                if (StringUtils.isNotBlank(filename)) {
                    filename = filename.replace(" ", "");
                    // 获取文件名
                    String fileName = filename.substring(0, filename.length() - 4);
                    String titleFilePaths = null;
                    SysAudios sysAudios = null;
                    SysVideos sysVideos = null;
                    // 1: 音频 2:视频
                    if (type == 1) {
                        // 存库音频全路径
                        titleFilePaths = titleAudiosPath + format + "/" + filename;
                        sysAudios = new SysAudios();
                        sysAudios.setAudioName(fileName);
                        sysAudios.setAudioPath(titleFilePaths);
                        sysAudios.setCreateBy(createName);
                        sysAudiosList.add(sysAudios);

                        sftpUtil.uploadList(multipartFile, sftpConfig.getRemoteRootPath(), sftp, filename);
                    } else {
                        // 存库视频全路径
                        titleFilePaths = titleVideosPath + format + "/" + filename;
                        sysVideos = new SysVideos();
                        sysVideos.setVideoName(fileName);
                        sysVideos.setVideoPath(titleFilePaths);
                        sysVideos.setCreateBy(createName);
                        sysVideosList.add(sysVideos);

                        sftpUtil.uploadList(multipartFile, sftpConfig.getRemoteRootPath(), sftp, filename);
                    }
                    log.info(type == 1 ? "音频" : "视频" +"——"+"文件上传-存库路径---:"+titleFilePaths);
                }
            }

            // 断开sftp连接
            sftpUtil.disConnect(sftp);
            // 储存数据
            if (sysAudiosList != null && sysAudiosList.size() != 0) {
                sysAudiosService.saveAudioInfo(sysAudiosList);
                log.info("音频信息入库成功");
            }
            if (sysVideosList != null && sysVideosList.size() != 0) {
                sysVideosService.saveVideoInfo(sysVideosList);
                log.info("视频信息入库成功");
            }
        }
        return ResponseResult.create().success(true).data(200);
    }
}

希望对你有所帮助!

手把手教你SpringBoot集成SFTP客户端实现文件上传下载 在项目开发中,一般文件存储很少再使用SFTP服务,但是也不排除合作伙伴使用SFTP来存储项目中的文件或者通过SFTP来实现文件数据的交互。我遇到的项目中,就有银行和保险公司等合作伙伴通过SFTP服务来实现与我们项目的文件数据的交互。其次我们引入了链接池工具,为了避免每次执行SFTP命令都要重新创建链接,我们使用池化的方式优化了比较消耗资源的创建操作。为了能够顺利地完成与友商的SFTP服务的连通,我们需要在自己的项目中实现一套SFTP客户端工具。对象池,这个才是真正的池子,它负责创建和存储所有的对象。 阅读详情

相关推荐

springboot整合sftp文件服务器实现文件上传下载功能

直接上模块代码 完整项目源码地址(参考ideal-sftp-1018模块):https://github.com/yangshilei/springCloud 1、项目结构 下面红圈中是主要的几个关于sftp客户端操作的对象方法。 2、添加sftp核心配置依赖 <!--sftp核心依赖包--> <dependency> <groupId>com.jcraft</groupId>

狗狗大蛇 2874

SpringBoot 整合sftp 实现文件的上传和下载

1.引入pom文件依赖 <!--sftp核心依赖包--> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.54</version> </dependency> 1.1pom文件详情 <?xml version="1.0...

xuewei_ing的博客 3644

手把手教你入门vue+springboot开发(二十)--文件上传下载

从去年10月份到12月底一直在参加阿里第六届数据库比赛,今年1,2月份又是春节假期,所以有5个月时间没有更新vue+springboot这个专题了,后续会继续跟大家一起学习研究。在业务开发场景中文件上传下载是个常用的基本功能,在C/S模式下我们一般使用ftp、tftp等文件传输服务器来实现。在vue+springboot的B/S模式下,如果传输的文件不大就没有必要使用文件传输服务器了,可以直接使用HTTP协议实现。本篇我们将通过一个简单的文件传输页面实例来研究一下HTTP协议如何实现文件传输,供大家参考。

dreamflyly的博客 1947

SpringBoot接口内部从sftp服务器获取文件流实现文件下载

SpringBoot接口内部从sftp服务器获取文件流实现文件下载

Be_insighted的博客 596

Spring Boot(六十三):使用sfpt实现简单的文件下载及上传

而SFTP协议是在FTP的基础上对数据进行加密,使得传输的数据相对来说更安全。但是这种安全是以牺牲效率为代价的,也就是说SFTP的传输效率比FTP要低(不过现实使用当中,没有发现多大差别)。之前项目遇到从文件服务器上传、下载、删除文件,一开始打算使用一些高级的文件系统,比如:FastDFS,GlusterFS,CephFS,这些高级厉害的文件存储系统,但是由于环境限制无法搭建,最终使用常用的FFTP或者SFTP实现文件上传和下载。2.SFTP更安全,但更安全带来副作用就是的效率比FTP要低些。

u013938578的博客 1928

SpringBoot连接Sftp服务器实现文件上传/下载(亲测可用)

本文介绍了一个基于JSch库实现的SFTP工具类,包含以下核心功能:1)通过POM依赖引入JSch组件;2)提供完整的SFTP工具类实现,支持连接测试、文件上传下载、目录递归创建等功能;3)封装了connect/disconnect方法管理连接,包含异常处理;4)实现文件存在性检查、自动创建远程目录等实用特性;5)提供使用示例代码。该工具类采用单例模式管理通道连接,通过try-with-resources确保资源释放,适合集成到Java项目中实现安全的SFTP文件传输功能。

黄团团的个人博客 439

springboot项目中通过sftp连接服务器实现简单的文件上传和下载

springboot项目中通过sftp连接服务器实现简单的文件上传和下载,代码注解详细。 新建springboot项目并在pom.xml文件中引入依赖 <!-- sftp上传依赖包 --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </depe

weixin_44499429的博客 1438

基于 Spring Boot 构建的文件摆渡系统(File Ferry System)

外网上传 → 中间服务器内网下载 ← 中间服务器基于 SFTP 的安全传输可扩展为 Web 系统、API 服务、后台任务等。

weixin_42551921的博客 322

springBoot整合sftp

springBoot整合sftp 1.引入依赖,pom文件添加依赖。 <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> 2.在application.yml文件添加sftp配置。 sftp: protocol:

winsanity的博客 4460

HMC5883L磁力计驱动开发:I²C通信、校准与FreeRTOS集成

磁力计是惯性导航与电子罗盘系统的核心传感器,其输出原始磁场数据需经精确采集、单位换算与误差补偿才能用于姿态解算。基于各向异性磁阻(AMR)原理的三轴磁力计,如HMC5883L,依赖稳定I²C通信获取12位有符号磁场采样值,并通过增益配置、硬软铁校准及温度补偿提升物理量精度。在嵌入式实时系统中,驱动层须保障数据的时间一致性与抗干扰鲁棒性,避免总线挂死、字节错位或量程误配等典型问题。本文围绕HMC5883L这一广泛使用的停产但仍在产线服役的磁传感器,详解寄存器配置、定点单位转换、八方位校准算法及FreeRTOS

weixin_42594427的博客 145

2026 具身智能 VLA/WAM 全栈学习与训练路线:从动作建模、SFT、RL 到世界模型的 RTX PRO 6000 96GB 单卡实战指南

我会把这张表做成“”而不是只列论文名:先核对每个模型截至的公开代码、训练目标和数据接口,再单独给你一套。对于没有公开、只有推理代码或训练细节不完整的模型,我会明确标出来,避免把“论文里提到”误写成“可复现”。目前有一个重要更新:。截至今天 NVIDIA 官方开源主线已经是换成 Cosmos-Reason2-2B/Qwen3-VL 架构,动作端仍是连续路线,而且官方明确给出单卡微调时默认只训练,峰值显存约。所以你的 96GB 单卡对 GR00T SFT 非常宽裕。可以。下面我按,把它整理成一张真正面向“

u013250861的博客 445

基于spring boot sftp文件上传

基于spring boot sftp文件上传 2018年06月21日 11:30:17 奇点_ 阅读数 3101 对sftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,sftp文件上传下载失败的重试。 application.yml配置文件 sftp: ip: 192.168.43.102 port: 22 ...

f45056231p的博客 747

利用 vivado实现加减法器的设计

本科计组实验:利用 vivado实现加减法器的设计

qq_52052302的博客 1万+

springboot上传下载文件(4)--上传下载工具类(已封装)

因为在做毕设,发现之前的搭建ftp文件服务器,通过ftp协议无法操作虚拟机临时文件,又因为ftp文件服务器搭建的比较麻烦;而 hadoop的HDFS虽然可以实现,但我这里用不到那么复杂的;所以我封装了一个文件上传下载的工具类,采用sftp协议. 简单方便可用性高!!! 本系列文章: springboot上传下载文件(1)(项目和文件资源放在同一个服务器上) springboot上传下载文...

小牛呼噜噜的博客 8527

随机截距交叉滞后模型RI-CLPM:原理、Mplus实现与结果解读

纵向面板数据分析中,传统交叉滞后模型(CLPM)常被用于探索变量间的时序关系,但其估计结果可能混淆了个体间稳定差异与个体内短期波动,导致交叉滞后路径出现偏差。随机截距交叉滞后模型(RI-CLPM)通过引入随机截距因子,将个体特质层面的差异与个体内动态过程分离,从而提供更纯净的个体内效应估计。该模型在组织心理学、发展心理学、成瘾行为等研究领域迅速普及,并成为顶级期刊审稿时常见的稳健性检验要求。本文从原理出发,系统讲解RI-CLPM的模型构建、识别条件、Mplus实操代码、输出解读及常见陷阱,并结合协变量处理、

weixin_33525298的博客 275

把 MANDT 锁进保险箱:ABAP Client Handling 与 Client Isolation(聚焦 AMDP 的 Client Safety )

本文探讨了ABAP系统中Client Handling与Client Isolation机制的演进,重点分析了AMDP环境下多租户隔离的风险与解决方案。传统ABAP SQL/CDS通过隐式Client过滤提供安全保障,而AMDP因其原生SQLScript特性容易绕过隔离机制。文章对比了旧时代依赖开发自觉的传参方式与新时代通过AMDP OPTIONS强约束的语法方案,详细介绍了CLIENT INDEPENDENT和CDS SESSION CLIENT DEPENDENT两种编译期安全机制,阐述了USING列表

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 341

SpringBoot-导出excel,ftp功能,异步功能,涉及比较多东西,有耐心可以好好看看

SpringBoot-导出excel,ftp功能,异步功能,涉及比较多东西,有耐心可以好好看看

黑科技的专栏 652

Modelsim:LPDDR5仿真(含美光仿真模型官方sv&vcs代码)

虽然,三星在设计跟量产上,早于其他家存储产商,但是镁光后来居上了,是业界首家支持全速 LPDDR5 的供应商,并且开发者在做开发的时候,也是用美光颗粒比较多,所以这里就先以美光的仿真模型为主进行仿真。 本工程为美光官方工程,支持Modelsim、VCS、ncverilog三种仿真器仿真。模型破解过,为完整system-verilog代码。

千歌叹尽执夏的博客 1283

Spring Boot实现SFTP文件上传下载

Spring Boot实现SFTP文件上传下载 1.实现背景及现实意义 近期由于系统迁移到docker容器,采用Spring Boot 框架实现微服务治理,在此基础上晚间批量文件服务器也由ftp改成sftp,由于之前ftp的实现是采用公具类的形式,在此基础之上,未屏蔽开发细节和依赖Spring Boot自动装配的特性,进行组件的自动装配和改造,旨在实现简化开发,提高文件传输的安全性和数据交互的可靠...

java界的小学生 9536

基于STM32L4XX、HAL库的YT8531C-CA以太网收发器(PHY)驱动程序设计

是一款由裕太微推出的高性价比、低功耗的单端口 10/100M 以太网物理层收发器(PHY)。它通过标准的 MII(介质独立接口)或 RMII(精简介质独立接口)与微控制器的 MAC 层连接,实现将数字信号与网络模拟信号之间的转换。支持自动协商(Auto-Negotiation),自动选择最高速率和双工模式。支持 HP Auto-MDIX(自动交叉直连),无需区分直通线或交叉线。低功耗设计,特别适合电池供电或对功耗敏感的 STM32L4 应用。支持 MII 和 RMII 接口,节省引脚(RMII模式)。

zhusl6688的博客 628

6、高通8155座舱平台--摄像头系统

在项目中遇到过,很多从手机转过来的工程师,上来就按手机那套调Camera,结果发现根本跑不通——为什么?我踩过这个坑——一开始想靠软件打时间戳来对齐,结果发现两个sensor的曝光时间不一样,时间戳根本对不上。我记得第一次调AWB时,怎么调颜色都不对,后来发现是BLC的参数没配好——黑电平偏了,后面所有颜色校正都是错的。上层应用说「我要拍张照」,HAL把它翻译成「ISP你给我处理这帧数据,sensor你给我曝光一次」。8155上推荐用camx,它是高通新一代的Camera框架,性能更好,而且支持多路同步。

woailuojp的博客 59

Spring Boot 集成 SFTP 文件上传和下载功能

文章目录1 摘要2 核心 Maven 依赖3 核心代码3.1 核心 SFTP 上传下载工具类3.2 SFTP 附件上传配置3.3 SFTP 附件上传与下载示例4 测试5 推荐参考资料6 本次提交记录 ​ ​ 1 摘要 在项目中附件上传和下载是一个常用的功能。可采用的方案有三种,第一种,将附件保存至应用服务器上,这一种应对少量不重要附件可以使用,但对于大量附件或者有重要附件的,不建议使用;第二种,将附件保存至专门的文件服务器上,这一种可应对大量、重要的附件,但是需要自行架设大存储空间的服务器;第三种保存至类似

Mrqiang9001 6409

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Springboot sftp实现文件上传下载

实现sftp 上传下载需要引入jsch-0.1.54.jar jsch 包地址:链接: https://pan.baidu.com/s/1eOUu0CXE-iIaWB8IuT5AkA 提取码: 6src maven 配置 com.jcraft jsch 0.1.54 代码: import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; ...

qq_45567515的博客 1188

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java优雅使用连接池连接SFTP进行文件上传下载 解决请求量大问题

# Java优雅使用连接池连接SFTP进行文件上传下载 解决请求量大问题 > 使用FTP连接池降低资源消耗,提高响应速率 ## 为什么要使用连接池连接SFTP呢? 在Java中使用连接池来连接SFTP(Secure File Transfer Protocol)工具的原因主要与性能、资源管理和效率有关。以下是一些关键原因:

AstarCloud 2693

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

FTP、SFTP安装,整合Springboot教程

在一般项目开发工程中,我们大多数会使用文件服务,比如上传图片、各种文档之类的。供我们选择的方式很多,比如第一种直接通过Java的File对象存储在本地,然后部署时候修改linux环境下的路径,这种方式简单粗暴;第二种就是在连网的情况下,直接使用OSS对象存储,比如阿里云OSS对象存储,当然这种是要花钱的,如果不花钱的话,也可以自己本地搭建一个OSS本地对象存储;

qq_39853669的博客 1815

springboot 连接sftp服务器

1.ftp和sftp主要区别 FTP是一种文件传输协议,一般是为了方便数据共享的。包括一个FTP服务器和多个FTP客户端。FTP客户端通过FTP协议在服务器上下载资源。而SFTP协议是在FTP的基础上对数据进行加密,使得传输的数据相对来说更安全。但是这种安全是以牺牲效率为代价的,也就是说SFTP的传输效率比FTP要低(不过现实使用当中,没有发现多大差别)。个人肤浅的认为就是:一;FTP要安装,S...

weixin_42338444的博客 2139
上一篇: java 文件上传下载
下一篇: Springboot 集成 kafka,配合使用spring线程池
WWWh0209
博客等级 码龄7年 9粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值