zoukankan      html  css  js  c++  java
  • springboot SFTP 文件上传下载功能

    新增sftp.properies

    文件保存 sftp服务器信息

    # 协议
    sftp.client.protocol=sftp
    # ip地址
    sftp.client.host=改成自己的文件服务器地址
    # 端口
    sftp.client.port=22
    # 用户名
    sftp.client.username=root
    # 密码
    sftp.client.password=改成自己的密码
    # 文件上传根路径
    sftp.client.root=/home/sftp/
    # 密钥文件路径
    sftp.client.privateKey=
    # 密钥的密码
    sftp.client.passphrase=
    #
    sftp.client.sessionStrictHostKeyChecking=no
    # session连接超时时间
    sftp.client.sessionConnectTimeout=15000
    # channel连接超时时间
    sftp.client.channelConnectedTimeout=15000

    SftpProperties.java 文件

    package cn.rc.properties;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    @Data
    @Component
    public class SftpProperties {
        @Value("${sftp.client.host}")
        private String host;
    
        @Value("${sftp.client.port}")
        private Integer port;
    
        @Value("${sftp.client.protocol}")
        private String protocol;
    
        @Value("${sftp.client.username}")
        private String username;
    
        @Value("${sftp.client.password}")
        private String password;
    
        @Value("${sftp.client.root}")
        private String root;
    
        @Value("${sftp.client.privateKey}")
        private String privateKey;
    
        @Value("${sftp.client.passphrase}")
        private String passphrase;
    
        @Value("${sftp.client.sessionStrictHostKeyChecking}")
        private String sessionStrictHostKeyChecking;
    
        @Value("${sftp.client.sessionConnectTimeout}")
        private Integer sessionConnectTimeout;
    
        @Value("${sftp.client.channelConnectedTimeout}")
        private Integer channelConnectedTimeout;
    
    }

    Application.java   文件启动类

    引入属性加上文件上传大小的设置

    /**
     * Eureka服务端
     *
     * @author wanjun
     */
    @SpringBootApplication
    @EnableDiscoveryClient
    @Slf4j
    @MapperScan(basePackages = {"cn.rc.mapper"})
    @PropertySource({"sftp.properties"})
    public class Application {
    
        public static void main(String[] args) throws Exception {
            SpringApplication.run(Application.class, args);
        }
    
        /**
         * 文件上传配置
         * @return
         */
        @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultipartConfigFactory factory = new MultipartConfigFactory();
            //文件最大
            //factory.setMaxFileSize("1024KB"); //KB,MB
            /// 设置总上传数据总大小
            factory.setMaxRequestSize("20480KB"); //最大上传为4M
            return factory.createMultipartConfig();
        }
    }
    
    

    文件上传下载的接口

    FileSystemController.java

    package cn.rc.controller;
    
    import cn.rc.properties.SftpProperties;
    import cn.rc.service.FileSystemService;
    import com.oracle.tools.packager.Log;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.multipart.MultipartHttpServletRequest;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.util.List;
    
    @Controller
    public class FileSystemController {
        @Autowired
        private FileSystemService fileSystemService;
    
        /**
         * 实现多文件上传
         */
        @RequestMapping(value = "upload", method = RequestMethod.POST)
        @ResponseBody
        public Boolean upload(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request) {
            if (files.isEmpty()) {
                return false;
            }
            for (MultipartFile file : files) {
                String fileName = file.getOriginalFilename();
                int size = (int) file.getSize();
                System.out.println(fileName + "-->" + size);
                if (file.isEmpty()) {
                    return false;
                } else {
                    try {
                        File dest = multipartFileToFile(file);
                        fileSystemService.uploadFile("/513_education/" + fileName, dest);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
                }
            }
            return true;
        }
    
    
        @RequestMapping("/download")
        public String downLoad(HttpServletResponse response) throws Exception {
            String downUrl = "/home/sftp/513_education/" + "20200225223754.csv";
            File file = fileSystemService.downloadFile(downUrl);
            String filename = file.getName();
            if (file.exists()) { //判断文件父目录是否存在
                response.setContentType("application/vnd.ms-excel;charset=UTF-8");
                response.setCharacterEncoding("UTF-8");
                // response.setContentType("application/force-download");
                response.setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode(filename, "UTF-8"));
                byte[] buffer = new byte[1024];
                FileInputStream fis = null; //文件输入流
                BufferedInputStream bis = null;
    
                OutputStream os = null; //输出流
                try {
                    os = response.getOutputStream();
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer);
                        i = bis.read(buffer);
                    }
    
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("----------file download---" + filename);
                try {
                    bis.close();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
    
        public static File multipartFileToFile(MultipartFile multiFile) {
            // 获取文件名
            String fileName = multiFile.getOriginalFilename();
            // 获取文件后缀
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            // 若需要防止生成的临时文件重复,可以在文件名后添加随机码
    
            try {
                File file = File.createTempFile(fileName, prefix);
                multiFile.transferTo(file);
                return file;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    FileSystemService
    package cn.rc.service;
    
    import java.io.File;
    import java.io.InputStream;
    
    public interface FileSystemService {
    
        boolean uploadFile(String targetPath, InputStream inputStream) throws Exception;
    
        boolean uploadFile(String targetPath, File file) throws Exception;
    
        File downloadFile(String targetPath) throws Exception;
    
        boolean deleteFile(String targetPath) throws Exception;
    }


    FileSystemServiceImpl.java
    package cn.rc.service.impl;
    
    import cn.rc.properties.SftpProperties;
    import cn.rc.service.FileSystemService;
    import com.jcraft.jsch.*;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.io.*;
    import java.util.Arrays;
    
    @Slf4j
    @Service("fileSystemService")
    public class FileSystemServiceImpl implements FileSystemService {
    
        @Autowired
        private SftpProperties config;
    
        // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
        private static final String SESSION_CONFIG_STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
    
        /**
         * 创建SFTP连接
         *
         * @return
         * @throws Exception
         */
        private ChannelSftp createSftp() throws Exception {
            JSch jsch = new JSch();
            log.info("Try to connect sftp[" + config.getUsername() + "@" + config.getHost() + "], use password[" + config.getPassword() + "]");
    
            Session session = createSession(jsch, config.getHost(), config.getUsername(), config.getPort());
            session.setPassword(config.getPassword());
            session.connect(config.getSessionConnectTimeout());
    
            log.info("Session connected to {}.", config.getHost());
    
            Channel channel = session.openChannel(config.getProtocol());
            channel.connect(config.getChannelConnectedTimeout());
    
            log.info("Channel created to {}.", config.getHost());
    
            return (ChannelSftp) channel;
        }
    
        /**
         * 加密秘钥方式登陆
         *
         * @return
         */
        private ChannelSftp connectByKey() throws Exception {
            JSch jsch = new JSch();
    
            // 设置密钥和密码 ,支持密钥的方式登陆
            if (StringUtils.isNotBlank(config.getPrivateKey())) {
                if (StringUtils.isNotBlank(config.getPassphrase())) {
                    // 设置带口令的密钥
                    jsch.addIdentity(config.getPrivateKey(), config.getPassphrase());
                } else {
                    // 设置不带口令的密钥
                    jsch.addIdentity(config.getPrivateKey());
                }
            }
            log.info("Try to connect sftp[" + config.getUsername() + "@" + config.getHost() + "], use private key[" + config.getPrivateKey()
                    + "] with passphrase[" + config.getPassphrase() + "]");
    
            Session session = createSession(jsch, config.getHost(), config.getUsername(), config.getPort());
            // 设置登陆超时时间
            session.connect(config.getSessionConnectTimeout());
            log.info("Session connected to " + config.getHost() + ".");
    
            // 创建sftp通信通道
            Channel channel = session.openChannel(config.getProtocol());
            channel.connect(config.getChannelConnectedTimeout());
            log.info("Channel created to " + config.getHost() + ".");
            return (ChannelSftp) channel;
        }
    
        /**
         * 创建session
         *
         * @param jsch
         * @param host
         * @param username
         * @param port
         * @return
         * @throws Exception
         */
        private Session createSession(JSch jsch, String host, String username, Integer port) throws Exception {
            Session session = null;
    
            if (port <= 0) {
                session = jsch.getSession(username, host);
            } else {
                session = jsch.getSession(username, host, port);
            }
    
            if (session == null) {
                throw new Exception(host + " session is null");
            }
    
            session.setConfig(SESSION_CONFIG_STRICT_HOST_KEY_CHECKING, config.getSessionStrictHostKeyChecking());
            return session;
        }
    
        /**
         * 关闭连接
         *
         * @param sftp
         */
        private void disconnect(ChannelSftp sftp) {
            try {
                if (sftp != null) {
                    if (sftp.isConnected()) {
                        sftp.disconnect();
                    } else if (sftp.isClosed()) {
                        log.info("sftp is closed already");
                    }
                    if (null != sftp.getSession()) {
                        sftp.getSession().disconnect();
                    }
                }
            } catch (JSchException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * 将inputStream上传到指定路径下(单级或多级目录)
         *
         * @param targetPath  路径+文件名  比如/ home/513_education/test.xlsl
         * @param inputStream
         * @return
         * @throws Exception
         */
        @Override
        public boolean uploadFile(String targetPath, InputStream inputStream) throws Exception {
            ChannelSftp sftp = this.createSftp();
            try {
                sftp.cd(config.getRoot());
                log.info("Change path to {}", config.getRoot());
    
                int index = targetPath.lastIndexOf("/");
                String fileDir = targetPath.substring(0, index);
                String fileName = targetPath.substring(index + 1);
                boolean dirs = this.createDirs(fileDir, sftp);
                if (!dirs) {
                    log.error("Remote path error. path:{}", targetPath);
                    throw new Exception("Upload File failure");
                }
                sftp.put(inputStream, fileName);
                return true;
            } catch (Exception e) {
                log.error("Upload file failure. TargetPath: {}", targetPath, e);
                throw new Exception("Upload File failure");
            } finally {
                this.disconnect(sftp);
            }
        }
    
    
        /**
         * 创建多级目录
         *
         * @param dirPath
         * @param sftp
         * @return
         */
        private boolean createDirs(String dirPath, ChannelSftp sftp) {
            if (dirPath != null && !dirPath.isEmpty()
                    && sftp != null) {
                String[] dirs = Arrays.stream(dirPath.split("/"))
                        .filter(StringUtils::isNotBlank)
                        .toArray(String[]::new);
    
                for (String dir : dirs) {
                    try {
                        sftp.cd(dir);
                        log.info("Change directory {}", dir);
                    } catch (Exception e) {
                        try {
                            sftp.mkdir(dir);
                            log.info("Create directory {}", dir);
                        } catch (SftpException e1) {
                            log.error("Create directory failure, directory:{}", dir, e1);
                            e1.printStackTrace();
                        }
                        try {
                            sftp.cd(dir);
                            log.info("Change directory {}", dir);
                        } catch (SftpException e1) {
                            log.error("Change directory failure, directory:{}", dir, e1);
                            e1.printStackTrace();
                        }
                    }
                }
                return true;
            }
            return false;
        }
    
    
        /**
         * 将文件上传到指定目录
         *
         * @param targetPath
         * @param file
         * @return
         * @throws Exception
         */
        @Override
        public boolean uploadFile(String targetPath, File file) throws Exception {
            return this.uploadFile(targetPath, new FileInputStream(file));
        }
    
        /**
         * 下载文件
         *
         * @param targetPath
         * @return
         * @throws Exception
         */
        @Override
        public File downloadFile(String targetPath) throws Exception {
            ChannelSftp sftp = this.createSftp();
            OutputStream outputStream = null;
            try {
                sftp.cd(config.getRoot());
                log.info("Change path to {}", config.getRoot());
    
                File file = new File(targetPath.substring(targetPath.lastIndexOf("/") + 1));
    
                outputStream = new FileOutputStream(file);
                sftp.get(targetPath, outputStream);
                log.info("Download file success. TargetPath: {}", targetPath);
                return file;
            } catch (Exception e) {
                log.error("Download file failure. TargetPath: {}", targetPath, e);
                throw new Exception("Download File failure");
            } finally {
                if (outputStream != null) {
                    outputStream.close();
                }
                this.disconnect(sftp);
            }
        }
    
        /**
         * 删除文件
         *
         * @param targetPath
         * @return
         * @throws Exception
         */
        @Override
        public boolean deleteFile(String targetPath) throws Exception {
            ChannelSftp sftp = null;
            try {
                sftp = this.createSftp();
                sftp.cd(config.getRoot());
                sftp.rm(targetPath);
                return true;
            } catch (Exception e) {
                log.error("Delete file failure. TargetPath: {}", targetPath, e);
                throw new Exception("Delete File failure");
            } finally {
                this.disconnect(sftp);
            }
        }
    }

    启动项目并用postman测试

    选择文件后请求,响应true

    查看控制台打印输出:

    登陆文件服务器 查看相应目录下:

    文件已经被上传

  • 相关阅读:
    PythonのTkinter基本原理
    使用 Word (VBA) 分割长图到多页
    如何使用 Shebang Line (Python 虚拟环境)
    将常用的 VBScript 脚本放到任务栏 (Pin VBScript to Taskbar)
    关于 VBScript 中的 CreateObject
    Windows Scripting Host (WSH) 是什么?
    Component Object Model (COM) 是什么?
    IOS 打开中文 html 文件,显示乱码的问题
    科技发展时间线(Technology Timeline)
    列置换密码
  • 原文地址:https://www.cnblogs.com/wanjun-top/p/12967795.html
Copyright © 2011-2022 走看看