SpringBoot上传文件到远程服务器(二十九)

Posted 两个蝴蝶飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot上传文件到远程服务器(二十九)相关的知识,希望对你有一定的参考价值。

风,将吹拂着我们的墓碑

上一章简单介绍了SpringBoot导入和导出Csv文件(二十八),如果没有看过,请观看上一章

前两个章节,我们学习了上传文件到本地服务器,这一章节,老蝴蝶和大家一起,上传文件到远程服务器.

上传文件到远程服务器,可以通过 FTP 或者 SSH 技术.

本章节的技术,依赖于 hutool 技术

关于 SSH 的技术,可以查看文档: Jsch(SSH)工具-JschUtil

关于 FTP 的技术,可以查看文档: FTP客户端封装-Ftp

本文章 采用 一个接口,两个实现 (SSH实现和 FTP实现) 的方式,进行演示.

一定要先学习一下,老蝴蝶写的: SpringBoot自定义Starter(二十四) 文章内容

本章节的代码目录结构如下:

一. FTP和SSH 实现文件上传和下载公共配置

一. 一 pom.xml 添加依赖

 <!--添加hutools工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.5</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>

一.二 配置文件进行配置

application.yml 配置文件

server:
  port: 7011
  servlet:
    context-path: /File
# 进行配置
file:
  useftp: true   # 是否使用 ftp, 为false表示使用 ssh上传
  ssh:
    host: 192.168.56.103   #已经配置了 ftp服务
    port: 21
    username: ftpuser  #对应的用户名和密码
    password: ftpuser
    uploadFilePath: /home/ftpuser/   #上传文件的路径
    downloadFilePath: D:/    #下载到哪个文件
spring:
  # 配置thymeleaf的相关信息
  thymeleaf:
    # 开启视图解析
    enabled: true
    #编码格式
    encoding: UTF-8
    #前缀配置
    prefix: classpath:/templates/
    # 后缀配置
    suffix: .html
    #是否使用缓存 开发环境时不设置缓存
    cache: false
    # 格式为 HTML 格式
    mode: HTML5
    # 配置类型
    servlet:
      content-type: text/html
  #配置上传的文件信息
  servlet:
    multipart:
      max-file-size: 100MB   # 服务器端文件大小限制
      max-request-size: 100MB  # 客户端请求文件大小限制
  profiles:
    # 配置谁生效
    active: ftp    # 注意这一个属性,表示哪一个实现被使用到

一.三 用属性类接收 file部分的配置内容

在 pojo 包下,添加配置类 SshFileProperties.java , 用于接收配置的属性

@Data
@Component
@ConfigurationProperties(prefix ="file.ssh" )
public class SshFileProperties 
    private static final String DEFAULT_HOST="127.0.0.1";
    private static final Integer DEFAULT_PORT=22;
    private static final String DEFAULT_USERNAME="";
    private static final String DEFAULT_PASSWORD="";
    private static final String DEFAULT_UPLOAD_FILEPATH="/usr/local/";
    private static final String DEFAULT_DOWNLOAD_FILEPATH="/usr/local/";

    private String host=DEFAULT_HOST;
    private Integer port=DEFAULT_PORT;
    private String username=DEFAULT_USERNAME;
    private String password=DEFAULT_PASSWORD;
    private String uploadFilePath=DEFAULT_UPLOAD_FILEPATH;
    private String downloadFilePath=DEFAULT_DOWNLOAD_FILEPATH;


一.四 配置接口

创建接口 FileService.java

public interface FileService 
    /**
     * 上传文件
     * @date 2021/11/5 11:52
     * @author zk_yjl
     * @param file 上传的文件
     * @param path 上传的文件的名称
     * @return String 上传后文件的路径
     */
    default String upload(String dest,String name,File file)
        return dest+name;
    
    /**
     * 上传文件
     * @date 2021/11/5 11:52
     * @author zk_yjl
     * @param file 上传的文件
     * @param path 上传的文件的名称
     * @return String 上传后文件的路径
     */
    default String pathUpload(String path,File file)
        return path;
    
    /**
     * 下载文件
     * @date 2021/11/5 11:54
     * @author zk_yjl
     * @param fileName  下载的文件名称
     * @param outFile  下载到的文件
     * @return void
     */
    default void download(String dest,String fileName,File outFile)

    
    /**
     * 下载文件,以绝对路径进行下载.
     * @date 2021/11/5 11:54
     * @author zk_yjl
     * @param path  下载的文件的路径
     * @param outFile  下载到的文件
     * @return void
     */
    default void pathDownload(String path,File outFile)

    


二. FTP 和 SSH 接口实现

二. 一 FTP 配置

主要是一个工具类 FtpUtil

@Configuration
@Log4j2
public class FtpUtil 
    @Autowired
    private SshFileProperties sshFileProperties;
    @Value("$file.useftp")
    private Boolean useftp;
    /**
     * 创建连接
     * @date 2021/11/5 17:21
     * @author zk_yjl
     * @param
     * @return org.apache.commons.net.ftp.FTPClient
     */
    public FTPClient createFileClient()
       if(!useftp)
           return null;
       
       FTPClient ftpClient=new FTPClient();
       try
           ftpClient.setControlEncoding("gbk");
           ftpClient.connect(sshFileProperties.getHost(), sshFileProperties.getPort());
           ftpClient.login(sshFileProperties.getUsername(), sshFileProperties.getPassword());
           ftpClient.enterLocalPassiveMode();
           // 设置上传目录
           ftpClient.setBufferSize(1024);
           ftpClient.setConnectTimeout(10 * 1000);
           ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
           return ftpClient;
       catch (Exception e)
           log.error("创建FTP服务器失败,",e);
       
        return ftpClient;
    
    /**
     * 关闭连接
     * @date 2021/11/5 17:21
     * @author zk_yjl
     * @param ftpClient
     * @return void
     */
    public void close(FTPClient ftpClient)
        try 
           if(ftpClient!=null)
               ftpClient.disconnect();
           
         catch (IOException e) 
            throw new RuntimeException("关闭FTP连接发生异常!", e);
        
    

二.二 SSH配置

主要是一个配置类 SftpConfig

@Configuration
public class SftpConfig 
   @Autowired
   private SshFileProperties sshFileProperties;
   @Value("$file.useftp")
   private Boolean useftp;

    @Bean
    public Sftp getSftp() 
        if(useftp)
            return null;
        
        return createSftp(
            sshFileProperties.getHost(), sshFileProperties.getPort(), sshFileProperties.getUsername(), sshFileProperties.getPassword()); 

    @Bean
    public Session getSession() 
        if(useftp)
            return null;
        
        return createSession(sshFileProperties.getHost(),
                sshFileProperties.getPort(),
                sshFileProperties.getUsername(),
                sshFileProperties.getPassword());
    

    public static Sftp createSftp(String sshHost, int sshPort, String sshUser, String sshPass) 
        return JschUtil.createSftp(sshHost, sshPort, sshUser, sshPass);
    

    public static Session createSession(String sshHost, int sshPort, String sshUser, String sshPass) 
        return JschUtil.getSession(sshHost, sshPort, sshUser, sshPass);
    


二.三 通过不同的环境,选择不同的实现

@Configuration
public class JavaConfig 

    @Autowired(required = false)
    private Sftp sftp;

    @Autowired(required = false)
    private FtpUtil ftpUtil;

    /**
     条件符合时,创建
     */
    @Bean("fileService")
    @Profile("ftp")
    FileService ftp()
        return new FtpFileServiceImpl(ftpUtil);
    
    /**
     条件符合时,创建
     */
    @Bean("fileService")
    @Profile("sftp")
    FileService cat()
        return new SftpFileServiceImpl(sftp);
    

二.四 不同的实现

二.四.一 FTP 实现

FtpFileServiceImpl.java

@Log4j2
public class FtpFileServiceImpl implements FileService 

    private FtpUtil ftpUtil;
    public FtpFileServiceImpl(FtpUtil ftpUtil)
        this.ftpUtil=ftpUtil;
    
    @Override
    public String upload(String dest,String fileName, File file) 
        if(StringUtils.isEmpty(fileName))
            fileName=file.getName();
        
        FTPClient ftpClient=null;
        //切换到相应的目录
       try
           ftpClient=ftpUtil.createFileClient();
           boolean isExistDir = ftpClient.changeWorkingDirectory(dest);
           if(!isExistDir)
               ftpClient.makeDirectory(dest);
               ftpClient.changeWorkingDirectory(dest);
           
           //保存文件
           ftpClient.storeFile(fileName,new FileInputStream(file));
           log.info("上传文件成功");
           return dest+fileName;
       catch (Exception e)
           log.error("上传文件失败,",e);
       finally
           ftpUtil.close(ftpClient);
       
       return null;
    

    @Override
    public String pathUpload(String path, File file) 
        //切换到相应的目录
        String[] split = path.split(File.separator);
        int size=split.length;
        FTPClient ftpClient=null;
        try
            ftpClient=ftpUtil.createFileClient();
            for (int i=0;i<size-2;i++) 
                String tempPath=split[i];
                if (StringUtils.isEmpty(tempPath)) 
                    continue;
                
                if (!ftpClient.changeWorkingDirectory(tempPath)) 
                    ftpClient.makeDirectory(tempPath);
                    ftpClient.changeWorkingDirectory(tempPath);
                
            
            //保存文件
            ftpClient.storeFile(split[size-1],new FileInputStream(file));
            log.info("上传文件成功");
            return path;
        catch (Exception e)
            log.error("上传文件失败,",e);
        finally 
            ftpUtil.close(ftpClient);
        
        return null;
    

    @Override
    public void download(String dest,String fileName, File outFile) 
        pathDownload(dest+fileName,outFile);
    
    @Override
    public void pathDownload(String path, File outFile) 
        FTPClient ftpClient=null;
        try 
            ftpClient=ftpUtil.createFileClient();
            ftpClient.retrieveFile(path,new FileOutputStream(outFile));
         catch (IOException e) 
            e.printStackTrace();
        finally 
            ftpUtil.close(ftpClient);
        
    

二.四.二 SFTP 实现

@Log4j2
public class SftpFileServiceImpl implements FileService 
    private Sftp sftp;
    public SftpFileServiceImpl(Sftp sftp)
        this.sftp=sftp;
    
    @Override
    public String upload(String dest,String fileName, File file) 
        if(StringUtils.isEmpty(fileName))
            fileName=file.getName();
        
        try 
            sftp.cd(dest);
         catch (Exception e) 
            log.info("该文件夹不存在,自动创建");
            sftp.mkdir(dest);
        
        try
            sftp.getClient().put(
                    new FileInputStream(file),
                    dest+fileName
            );
            log.info(">>>文件上传成功");
            return dest+fileName;
        catch (Exception e)
            log.error("文件上传失败,",e);
            return null;
        
    

    @Override
    public String pathUpload(String path, File file) 
        try
            sftp.getClient().put(new FileInputStream(file),path);
        catch (Exception e)
            log.error("文件上传失败,",e);
            return null;
        
        return null;
    

    @Override
    public void download(String dest,String fileName, File outFile) 
        sftp.download(dest+fileName,outFile);
    
    @Override
    public void pathDownload(String path, File outFile) 
        sftp.download(path,outFile);
    

二.五 controller 控制器

@Controller
public class FileController 

    @Autowired
    private FileService fileService;

    @Autowired
    private SshFileProperties sshFileProperties;


    @RequestMapping("/")
    public String index()
        return "index";
    
    @PostMapping("/upload")
    @ResponseBody
    public String upload(MultipartFile file, HttpServletRequest request) throws IOException 
        // 获得 classpath 的绝对路径
        String realPath = ResourceUtils.getURL("classpath:").getPath()+"static/files";
        File newFile = new File(realPath);
        // 如果文件夹不存在、则新建
        if (!newFile.exists())
   

以上是关于SpringBoot上传文件到远程服务器(二十九)的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学安全(二十九)●上传漏洞代码分析

SpringBoot入门十九,简单文件上传

第二十九章 springboot + zipkin + mysql

SpringBoot入门二十九,整合Swagger3

ROS从入门到精通系列(二十九)-- linux封装ROS 自启动脚本及可执行程序App

linux (二十九)PXE的原理及部署