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

maven依赖:

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

application.yml

sftp:
  protocol: sftp
  host: 
  port: 22
  username: root
  password: 
  
spring:
  servlet:
    multipart:
      max-file-size: 500MB
      max-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 {
    @Resource
    private 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 {

    @Autowired
    private 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 {
    @Autowired
    private SftpUtils sftpUtils;

    @Override
    public 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 {
            // 关闭sftp
            sftpUtils.disconnect(sftp);
        }
    }

    @Override
    public 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 {
            // 关闭sftp
            sftpUtils.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;
        }
    }
}

接口测试:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值