From 97c9501dc0aaf0512b67d154f17257079ad74e55 Mon Sep 17 00:00:00 2001 From: gaorl Date: Sat, 3 Jun 2023 12:23:22 +0800 Subject: [PATCH] =?UTF-8?q?feature=EF=BC=9A=E6=B7=BB=E5=8A=A0ssh=E7=9A=84f?= =?UTF-8?q?tp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/dxhy/oss/config/OssReturnConfig.java | 2 + .../java/com/dxhy/oss/service/FtpService.java | 7 +- .../java/com/dxhy/oss/service/SshService.java | 166 ++++++++++++++++++ .../oss/service/impl/FileServiceImpl.java | 57 +++++- .../java/com/dxhy/oss/utils/SshFactory.java | 70 ++++++++ .../main/java/com/dxhy/oss/utils/SshPool.java | 41 +++++ .../com/dxhy/oss/utils/SshProperties.java | 61 +++++++ 7 files changed, 393 insertions(+), 11 deletions(-) create mode 100644 dxhy-oss/src/main/java/com/dxhy/oss/service/SshService.java create mode 100644 dxhy-oss/src/main/java/com/dxhy/oss/utils/SshFactory.java create mode 100644 dxhy-oss/src/main/java/com/dxhy/oss/utils/SshPool.java create mode 100644 dxhy-oss/src/main/java/com/dxhy/oss/utils/SshProperties.java diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/config/OssReturnConfig.java b/dxhy-oss/src/main/java/com/dxhy/oss/config/OssReturnConfig.java index 22140e07..37d075a0 100644 --- a/dxhy-oss/src/main/java/com/dxhy/oss/config/OssReturnConfig.java +++ b/dxhy-oss/src/main/java/com/dxhy/oss/config/OssReturnConfig.java @@ -17,6 +17,8 @@ public interface OssReturnConfig { String FTP = "FTP"; + String SSH = "SSH"; + String LOCAL = "LOCAL"; String TOS = "TOS"; diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/FtpService.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/FtpService.java index 300ffd34..de591237 100644 --- a/dxhy-oss/src/main/java/com/dxhy/oss/service/FtpService.java +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/FtpService.java @@ -6,12 +6,14 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; +import org.springframework.stereotype.Service; import java.io.*; import java.util.ArrayList; import java.util.List; @Slf4j +@Service public class FtpService { private final SftpPool pool; @@ -50,9 +52,8 @@ public class FtpService { result =false; } finally { try { - if (ftpClient.isConnected()) { - ftpClient.disconnect(); - } + log.info("回收线程"); + pool.returnObject(ftpClient); if (null != inputStream) { inputStream.close(); } diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/SshService.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/SshService.java new file mode 100644 index 00000000..d1d63331 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/SshService.java @@ -0,0 +1,166 @@ +package com.dxhy.oss.service; + +import cn.hutool.core.io.FileUtil; +import com.dxhy.oss.utils.SshPool; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.SftpException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; + +/** + * @author jiaohongyang + */ +@Slf4j +@Service +public class SshService { + + private final SshPool pool; + + public SshService(SshPool pool) { + this.pool = pool; + } + + /** + * 将输入流的数据上传到sftp作为文件。文件完整路径 = basePath+directory + * + * @param pathName ftp服务保存地址,完整路径 + * @param fileName 上传到ftp的文件名 + * @param originFileName 待上传文件的名称(绝对地址) + */ + + public boolean uploadFile(String pathName, String fileName, String originFileName) { + log.info("开始上传文件"); + ChannelSftp sftp = null; + InputStream inputStream; + try { + sftp = pool.borrowObject(); + try { + sftp.cd(pathName); + } catch (SftpException e) { + // 目录不存在,则创建文件夹 + String[] dirs = pathName.split("/"); + String tempPath = ""; + for (String dir : dirs) { + if (null == dir || "".equals(dir)) { + continue; + } + tempPath += "/" + dir; + try { + sftp.cd(tempPath); + } catch (SftpException ex) { + try { + sftp.mkdir(tempPath); + sftp.cd(tempPath); + } catch (SftpException e1) { + e1.printStackTrace(); + } + } + } + } + + File orgFile = new File(originFileName); + inputStream = Files.newInputStream(orgFile.toPath()); + sftp.put(inputStream, fileName); + inputStream.close(); + // 删除本地文件,防止服务器空间不足 + FileUtil.del(orgFile); + log.info("上传文件成功"); + return true; + } catch (Exception e) { + e.printStackTrace(); + log.info("上传文件失败"); + return false; + } finally { + if (sftp != null) { + log.info("回收线程"); + pool.returnObject(sftp); + } + + } + } + + + public boolean downloadFile(String directory, String downloadFile, String saveFile) { + log.info("开始下载文件!"); + ChannelSftp sftp = null; + try { + sftp = pool.borrowObject(); + if (directory != null && !"".equals(directory)) { + sftp.cd(directory); + } + String file = saveFile + "/" + downloadFile; + File fileLocal = new File(file); + if (fileLocal.exists()) { + boolean delete = fileLocal.delete(); + log.info("删除本地路径文件:{}", delete); + } + this.directoryIsExists(saveFile); + sftp.get(downloadFile, file); + log.info("下载文件成功!"); + return true; + } catch (Exception e) { + e.printStackTrace(); + log.info("下载文件失败!"); + return false; + } finally { + if (sftp != null) { + log.info("回收线程"); + pool.returnObject(sftp); + } + + } + + + } + + + /** + * 删除文件 + * + * @param directory 要删除文件所在目录 + * @param deleteFile 要删除的文件 + * @return 返回是否删除成功 + */ + + public boolean deleteFile(String directory, String deleteFile) { + ChannelSftp sftp = null; + try { + sftp = pool.borrowObject(); + sftp.cd(directory); + sftp.rm(deleteFile); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } finally { + if (sftp != null) { + log.info("回收线程"); + pool.returnObject(sftp); + } + } + } + + + public void directoryIsExists(String path) { + File directory = new File(path); + if (directory.exists()) { + return; + } + + if (!directory.mkdir()) { + return; + } + + if (directory.canWrite()) { + return; + } + + boolean setWritable = directory.setWritable(true); + log.info("是否创建文件 directoryIsExists :{} ", setWritable); + + } +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/FileServiceImpl.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/FileServiceImpl.java index 8f948867..fc6d6563 100644 --- a/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/FileServiceImpl.java +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/FileServiceImpl.java @@ -4,10 +4,7 @@ import cn.hutool.core.io.FileUtil; import com.dxhy.oss.config.OssConfig; import com.dxhy.oss.config.OssReturnConfig; import com.dxhy.oss.model.FileModel; -import com.dxhy.oss.service.AliOssService; -import com.dxhy.oss.service.FileService; -import com.dxhy.oss.service.FtpService; -import com.dxhy.oss.service.JdOssService; +import com.dxhy.oss.service.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -27,13 +24,15 @@ public class FileServiceImpl implements FileService { private final AliOssService aliOssService; private final JdOssService jdOssService; private final FtpService ftpService; + private final SshService sshService; @Autowired - public FileServiceImpl(OssConfig ossConfig, AliOssService aliOssService, JdOssService jdOssService, FtpService ftpService) { + public FileServiceImpl(OssConfig ossConfig, AliOssService aliOssService, JdOssService jdOssService, FtpService ftpService, SshService sshService) { this.ossConfig = ossConfig; this.aliOssService = aliOssService; this.jdOssService = jdOssService; this.ftpService = ftpService; + this.sshService = sshService; } /** @@ -60,7 +59,22 @@ public class FileServiceImpl implements FileService { } fileModel = jdOssService.uploadFile(fileName, originFileName); - } else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { + } else if (OssReturnConfig.SSH.equals(ossConfig.getOssType())){ + if (!fileName.startsWith("/")) { + fileName = "/" + fileName; + } + String directory = fileName.substring(0, fileName.lastIndexOf("/")); + File directoryFile = new File(fileName); + String downloadFileName = directoryFile.getName(); + boolean b = sshService.uploadFile(directory, downloadFileName, originFileName); + fileModel = new FileModel(); + fileModel.setFilePath(fileName); + if (b) { + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel.setCode(OssReturnConfig.ERROR_09); + } + }else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { if (!fileName.startsWith("/")) { fileName = "/" + fileName; } @@ -131,6 +145,12 @@ public class FileServiceImpl implements FileService { return fileModel; } + /** + * + * @param downloadFile 下载文件 服务器路径 + * @param saveFile 保存文件地址 本地路劲 + * @return + */ @Override public FileModel downFile(String downloadFile, String saveFile) { log.info("下载文件地址:{} , 本地存储文件地址:{}", downloadFile, saveFile); @@ -149,7 +169,18 @@ public class FileServiceImpl implements FileService { downloadFile = downloadFile.substring(1); } fileModel = jdOssService.downloadFile(downloadFile, saveFile); - } else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { + } else if(OssReturnConfig.SSH.equals(ossConfig.getOssType())){ + String directory = downloadFile.substring(0, downloadFile.lastIndexOf("/")); + String downloadFileName = downloadFile.substring(downloadFile.lastIndexOf("/") + 1); + boolean b = sshService.downloadFile(directory, downloadFileName, path); + fileModel = new FileModel(); + fileModel.setFilePath(saveFile); + if (b) { + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel.setCode(OssReturnConfig.ERROR_09); + } + }else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { String directory = downloadFile.substring(0, downloadFile.lastIndexOf("/")); File directoryFile = new File(downloadFile); String downloadFileName = directoryFile.getName(); @@ -234,7 +265,17 @@ public class FileServiceImpl implements FileService { path = path.substring(1); } fileModel = jdOssService.deleteFile(path); - } else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { + } else if(OssReturnConfig.SSH.equals(ossConfig.getOssType())){ + File file = new File(path); + boolean b = sshService.deleteFile(file.getParent(), file.getName()); + if (b) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_01); + } + }else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { File file = new File(path); boolean b = ftpService.deleteFile(file.getParent(), file.getName()); if (b) { diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshFactory.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshFactory.java new file mode 100644 index 00000000..c3f157f3 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshFactory.java @@ -0,0 +1,70 @@ +package com.dxhy.oss.utils; + +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.impl.DefaultPooledObject; + +import java.util.Properties; + +@EqualsAndHashCode(callSuper = true) +@Data +@Slf4j +public class SshFactory extends BasePooledObjectFactory { + + private SshProperties ossConfig; + + public SshFactory(SshProperties ossConfig) { + this.ossConfig = ossConfig; + } + + @Override + public ChannelSftp create() throws SftpPoolException { + try { + JSch jsch = new JSch(); + Session session = jsch.getSession(ossConfig.getUsername(), ossConfig.getHostname(), Integer.parseInt(ossConfig.getPort())); + // 设置密码 + if (ossConfig.getPassword() != null) { + session.setPassword(ossConfig.getPassword()); + } + // 设置密码 + if (ossConfig.getPassword() != null) { + session.setPassword(ossConfig.getPassword()); + } + // 为Session对象设置properties + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + // 设置超时时间 + session.setTimeout(Integer.parseInt(ossConfig.getTimeout())); + // 建立链接 + session.connect(); + // 打开SFTP通道 + ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); + // 建立SFTP通道的连接 + channel.connect(); + return channel; + } catch (JSchException e) { + throw new SftpPoolException("获取ftp连接失败", e); + } + } + + @Override + public PooledObject wrap(ChannelSftp channelSftp) { + return new DefaultPooledObject<>(channelSftp); + } + + // 销毁对象 + @Override + public void destroyObject(PooledObject p) { + ChannelSftp channelSftp = p.getObject(); + channelSftp.disconnect(); + } + +} \ No newline at end of file diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshPool.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshPool.java new file mode 100644 index 00000000..9ce27258 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshPool.java @@ -0,0 +1,41 @@ +package com.dxhy.oss.utils; + +import com.jcraft.jsch.ChannelSftp; +import lombok.Data; +import org.apache.commons.pool2.impl.GenericObjectPool; + +@Data +public class SshPool { + + private GenericObjectPool pool; + + public SshPool(SshFactory factory) { + this.pool = new GenericObjectPool<>(factory, factory.getOssConfig().getPool()); + } + + /** + * 获取一个sftp连接对象 + * + * @return sftp连接对象 + */ + public ChannelSftp borrowObject() throws SftpPoolException { + try { + return pool.borrowObject(); + } catch (Exception e) { + e.printStackTrace(); + throw new SftpPoolException("获取ftp连接失败", e); + } + } + + /** + * 归还一个sftp连接对象 + * + * @param channelSftp sftp连接对象 + */ + public void returnObject(ChannelSftp channelSftp) { + if (channelSftp != null) { + pool.returnObject(channelSftp); + } + } + +} \ No newline at end of file diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshProperties.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshProperties.java new file mode 100644 index 00000000..2b82c304 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SshProperties.java @@ -0,0 +1,61 @@ +package com.dxhy.oss.utils; + +import com.jcraft.jsch.ChannelSftp; +import lombok.Data; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "ftp.connection") +public class SshProperties { + + private String hostname; + private String port = "22"; + private String username; + private String password; + private String timeout; + private Pool pool = new Pool(); + + public static class Pool extends GenericObjectPoolConfig { + + private int maxTotal = DEFAULT_MAX_TOTAL; + private int maxIdle = DEFAULT_MAX_IDLE; + private int minIdle = DEFAULT_MIN_IDLE; + + public Pool() { + super(); + } + + @Override + public int getMaxTotal() { + return maxTotal; + } + + @Override + public void setMaxTotal(int maxTotal) { + this.maxTotal = maxTotal; + } + + @Override + public int getMaxIdle() { + return maxIdle; + } + + @Override + public void setMaxIdle(int maxIdle) { + this.maxIdle = maxIdle; + } + + @Override + public int getMinIdle() { + return minIdle; + } + + @Override + public void setMinIdle(int minIdle) { + this.minIdle = minIdle; + } + + } + +} \ No newline at end of file