1、依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.54</version> </dependency>
2、配置(yml)
sftp: ip: 192.168.23.142 port: 22 username: root password: 123456 downloadSleep: 100 #文件下载失败下次超时重试时间 downloadRetry: 10 #文件下载失败重试次数 uploadSleep: 100 #文件上传失败下次超时重试时间 uploadRettry: 10 #文件上传失败重试次数
3、SFTPUtils
package com.zj.docker.utils; import com.jcraft.jsch.*; import org.springframework.scheduling.annotation.Async; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.lang.reflect.Field; import java.util.Properties; /** * @Auther: zj * @Date: 2018/12/18 16:58 * @Description: */ public class SFTPUtils { /** * 默认端口 */ private final static int DEFAULT_PORT = 22; private final static String HOST = "host"; private final static String PORT = "port"; private final static String USER_NAME = "userName"; private final static String PASSWORD = "password"; /** * 服务端保存的文件名 */ private String remote; /** * 服务端保存的路径 */ private String remotePath; /** * 本地文件 */ private File local; /** * 主机地址 */ private String host; /** * 端口 */ private int port = DEFAULT_PORT; /** * 登录名 */ private String userName; /** * 登录密码 */ private String password; private ChannelSftp sftp; public SFTPUtils(String host, int port, String userName, String password) { this.init(host, port, userName, password); } /** * 初始化 * * @param host * @param port * @param userName * @param password * @date 2018/12/18 */ private void init(String host, int port, String userName, String password) { this.host = host; this.port = port; this.userName = userName; this.password = password; } /** * 连接sftp * * @throws JSchException * @date 2018/12/18 */ private void connect() throws JSchException, NoSuchFieldException, IllegalAccessException, SftpException { JSch jsch = new JSch(); // 取得一个SFTP服务器的会话 Session session = jsch.getSession(userName, host, port); // 设置连接服务器密码 session.setPassword(password); Properties sessionConfig = new Properties(); // StrictHostKeyChecking // "如果设为"yes",ssh将不会自动把计算机的密匙加入"$HOME/.ssh/known_hosts"文件, // 且一旦计算机的密匙发生了变化,就拒绝连接。 sessionConfig.setProperty("StrictHostKeyChecking", "no"); // 设置会话参数 session.setConfig(sessionConfig); // 连接 session.connect(); // 打开一个sftp渠道 Channel channel = session.openChannel("sftp"); sftp = (ChannelSftp) channel; channel.connect(); Class cl = ChannelSftp.class; Field f =cl.getDeclaredField("server_version"); f.setAccessible(true); f.set(sftp, 2); sftp.setFilenameEncoding("GBK"); } /** * 上传文件 * @date 2018/12/18 */ public void uploadFile() throws Exception { FileInputStream inputStream = null; try { connect(); if (isEmpty(remote)) { remote = local.getName(); } if (!isEmpty(remotePath)) { sftp.cd(remotePath); } inputStream = new FileInputStream(local); sftp.put(inputStream, remote); } catch (Exception e) { throw e; } finally { sftp.disconnect(); close(inputStream); } } public void uploadFile(InputStream inputStream) throws Exception { try { connect(); if (isEmpty(remote)) { remote = local.getName(); } if (!isEmpty(remotePath)) { createDir(remotePath); } sftp.put(inputStream, remote); } catch (Exception e) { throw e; } finally { sftp.disconnect(); close(inputStream); } } @Async("taskExecutor")//异步 public void uploadFile(String filename, String filePath, MultipartFile file) throws Exception { try { connect(); if (!isEmpty( filePath )) { createDir( filePath ); } sftp.put( file.getInputStream(), filename ); }catch (Exception e) { throw e; } finally { sftp.disconnect(); close(file.getInputStream()); } } public boolean isDirExist(String directory) throws Exception { boolean isDirExistFlag = false; try { SftpATTRS sftpATTRS = sftp.lstat(directory); isDirExistFlag = true; return sftpATTRS.isDir(); } catch (Exception e) { if (e.getMessage().toLowerCase().equals("no such file")) { isDirExistFlag = false; } } return isDirExistFlag; } public void createDir(String createpath) throws Exception { try { if (isDirExist(createpath)) { this.sftp.cd(createpath); } else { String pathArry[] = createpath.split("/"); for (String path : pathArry) { if (path.equals("")) { continue; } if (isDirExist(path.toString())) { sftp.cd(path.toString()); } else { // 建立目录 sftp.mkdir(path.toString()); // 进入并设置为当前目录 sftp.cd(path.toString()); } } } } catch (SftpException e) { throw new Exception("创建路径错误:" + createpath); } } /** * 下载 * @date 2018/12/18 */ public void download() throws Exception { FileOutputStream output = null; try { this.connect(); if (null != remotePath || !("".equals(remotePath))) { sftp.cd(remotePath); } output = new FileOutputStream(local); sftp.get(remote, output); } catch (Exception e) { throw e; } finally { sftp.disconnect(); close(output); } } public void download(OutputStream outputStream) throws Exception { try { this.connect(); if (null != remotePath || !("".equals(remotePath))) { sftp.cd(remotePath); } sftp.get(remote, outputStream); } catch (Exception e) { throw e; } finally { sftp.disconnect(); } } public static boolean isEmpty(String str) { if (null == str || "".equals(str)) { return true; } return false; } public static void close(OutputStream... outputStreams) { for (OutputStream outputStream : outputStreams) { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void close(InputStream... inputStreams) { for (InputStream inputStream : inputStreams) { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void setRemote(String remote) { this.remote = remote; } public void setRemotePath(String remotePath) { this.remotePath = remotePath; } public void setLocal(File local) { this.local = local; } }
4、Controller
测试,这边就简单举了一个例子
@Value("${sftp.ip}") private String SFTP_ADDRESS; //ip @Value("${sftp.port}") private Integer SFTP_PORT; //port @Value("${sftp.username}") private String SFTP_USERNAME; //sftp username @Value("${sftp.password}") private String SFTP_PASSWORD; //sftp password -------------------------------------------------- /** * 上传文件到数据卷,普通用户权限 * @param request * @param name 数据卷的名称 * @param file 上传的文件 * @return * @throws Exception */ @PostMapping("/customer/uploadDocToVolume") public ResultVo customerUploadDocToVolume(HttpServletRequest request, @RequestParam("name") String name, @RequestParam("file") MultipartFile file ) throws Exception { //鉴权 String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() ); if (Objects.equals( username, CommonEnum.FALSE.getMessage())) { return ResultVoUtil.error(); } //校验参数 if (StringUtils.isBlank( name )||file==null ) { return ResultVoUtil.error(CommonEnum.PARAM_ERROR.getMessage()); } String bashPath ="/var/lib/docker/volumes/"; String picSavePath = "/"+name+"/_data"; SFTPUtils sftpUtils = new SFTPUtils( SFTP_ADDRESS,SFTP_PORT,SFTP_USERNAME,SFTP_PASSWORD); //上传文件,同步 sftpUtils.uploadFile( file.getOriginalFilename(),bashPath+picSavePath,file ); return ResultVoUtil.success("上传文件成功"); }
本篇文章到这里就结束啦,很感谢你能看到最后,欢迎关注!