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

1.引入pom文件依赖

<!--sftp核心依赖包-->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

        1.1 pom文件详情

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xuewei.study</groupId>
    <artifactId>study_sftp_demo</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--sftp核心依赖包-->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

 2. 新建application.yml文件

注意:

username :登录远程服务的用户名称

password:登录远程服务的密码

host:远程服务的地址

port:连接远程服务的端口

server:
  port: 9001

spring:
  application:
    name: study_sftp_service
  servlet:
    multipart:
      #      单个文件的大小不能超过该值
      max-file-size: 100MB
      #      单个请求最大的大小不能超过该值
      max-request-size: 1000MB

# 这里也可以直接作为成员变量写死在类里。这里的配置都是我自定义的,叫什么都可以。
remoteserver:
  username: root
  password: test001
  host: 10.45.156.200
  port: 22

3.项目目录结构预览

 

4. 编写主启动类

package com.xuewei.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * @Author: xuewei
 * @Date: 2022/3/17 16:36
 */
@SpringBootApplication(scanBasePackages = { "com.xuewei" })
public class SftpMain {
    public static void main(String[] args) {
        SpringApplication.run(SftpMain.class,args);
    }
}

 

5.编写配置类

注意:JSch登录sftp会进行Kerberos username 身份验证提示

如果需要跳过,需要添加配置如下:

config.put("PreferredAuthentications","publickey,keyboard-interactive,password");

package com.xuewei.study.config;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * Sftp配置
 * @Author: xuewei
 * @Date: 2022/3/17 16:41
 */
@Configuration
@Slf4j
public class SftpConnectConfig {

    /**
     * FTP 登录用户名
     */
    @Value("${remoteserver.username}")
    private String username;
    /**
     * FTP 登录密码
     */
    @Value("${remoteserver.password}")
    private String password;

    /**
     * FTP 服务器地址IP地址
     */
    @Value("${remoteserver.host}")
    private String host;

    /**
     * FTP 端口
     */
    @Value("${remoteserver.port}")
    private String strPort;

    private Session getSession() throws JSchException {
        JSch jsch = new JSch();
        int port = Integer.parseInt(strPort.trim());
        Session session = jsch.getSession(username, host, port);
        if (password != null) {
            session.setPassword(password);
        }
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        // JSch登录sftp,跳过 Kerberos username 身份验证提示
        config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
        session.setConfig(config);
        session.connect();
        return session;
    }

    /**
     * 连接sftp服务器,返回的是sftp连接通道,用来操纵文件
     * @throws Exception
     */
    @Bean
    public ChannelSftp channelSftp() {
        ChannelSftp sftp = null;
        try {
            Session session = getSession();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            log.error("连接失败",e);
        }
        return sftp;
    }

    /**
     * 连接sftp服务器,返回exec连接通道,可以远程执行命令
     * @throws Exception
     */
    @Bean
    public ChannelExec channelExec(){
        ChannelExec sftp = null;
        try {
            Session session = getSession();
            Channel channel = null;
            channel = session.openChannel("exec");
            channel.connect();
            sftp = (ChannelExec) channel;
        } catch (JSchException e) {
            log.error("连接失败",e);
            System.out.println("连接失败");
        }
        return sftp;
    }
}

6.编写控制器

package com.xuewei.study.controller;

import com.xuewei.study.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;

/**
 * @Author: xuewei
 * @Date: 2022/3/17 16:55
 */
@RestController
@Slf4j
public class FileController {


    @Autowired
    private FileService fileService;

    @GetMapping("/download")
    public void download(@RequestParam(required = true) String file, @RequestParam(required = true)String path,
                         HttpServletResponse response){
        //设置响应信息
        response.setContentType("application/octet-stream");
        // filename为文件下载后保存的文件名,可自行设置,但是注意文件名后缀,要和原来的保持一致
        response.setHeader("Content-Disposition", "attachment; filename=" + file);
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            // 输出到客户端
            out.write(fileService.download(path, file));
        } catch (Exception e) {
            log.error("",e);
        }
    }

    /**
     * 上传文件到服务器
     * @param file 要上传到服务器的文件,注意此处的path必须在结尾添加 /
     * @param path 上传到服务器的路径
     */
    @PostMapping("/upload")
    public void upload(@RequestBody(required = true) MultipartFile file, @RequestParam(required = true) String path){
        try {
            fileService.upload(file, path);
        } catch (Exception e) {
            log.error("",e);
        }
    }
}

7.编写业务类

package com.xuewei.study.service;

import com.jcraft.jsch.ChannelSftp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.UUID;

/**
 * @Author: xuewei
 * @Date: 2022/3/17 16:43
 */
@Service
@Slf4j
public class FileService {

    @Resource
    private ChannelSftp channelSftp;

    /**
     * 从服务器获取文件并返回字节数组
     * @param path 要下载文件的路径
     * @param file 要下载的文件
     */
    public byte[] download(String path, String file) throws Exception {
        // 切换到文件所在目录
        channelSftp.cd(path);
        //获取文件并返回给输入流,若文件不存在该方法会抛出常
        InputStream is = channelSftp.get(file);
        byte[] fileData = IOUtils.toByteArray(is);
        if(is != null){
            is.close();
        }
        return fileData;
    }

    /**
     * 将输入流的数据上传到sftp作为文件
     *
     * @param path
     *            上传到该目录
     * @param uploadFile
     *           服务器保存的文件
     * @throws Exception
     */
    public void upload(MultipartFile uploadFile, String path) throws Exception{
        String fileName = uploadFile.getOriginalFilename();
        // 用uuid + 原来的文件名生成新名字,防止文件名重复也可以辨识上传的文件是哪个,可以省略这一步
        String newName = UUID.randomUUID().toString().replaceAll("-","") + fileName;
        File file = new File(path + newName);
        //将MultipartFilez转换为File,会生成文件
        FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), file);
        // 如果该目录不存在则直接创建新的目录,并切换到该目录
        try {
            channelSftp.cd(path);
        } catch (Exception e) {
            channelSftp.mkdir(path);
            channelSftp.cd(path);
        }
        channelSftp.put(new FileInputStream(file), newName);
        // 操作完成,删除刚刚生成的文件
        file.delete();
    }
}

8.代码测试

8.1 文件下载

http://localhost:9001/download?file=test.txt&path=/home/test

 

 

8.2 文件上传

localhost:9001/upload

 

总结:打完收工,各位帅哥、美女。浏览完点个赞再走哦。 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值