springboot SFTP 文件上传下载功能
Posted 小污龟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
查看控制台打印输出:
登陆文件服务器 查看相应目录下:
文件已经被上传
以上是关于springboot SFTP 文件上传下载功能的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# java通过sftp模式实现FTP的文件上传下载删除功能
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)八(文件的上传FastDFS和校验)(Nginx的请求前缀配置,在发布项目的时候要注意)(代