diff --git a/dxhy-core/pom.xml b/dxhy-core/pom.xml index 53abe822..45cd4923 100644 --- a/dxhy-core/pom.xml +++ b/dxhy-core/pom.xml @@ -150,7 +150,7 @@ com.dxhy.jxpt dxhy-oss - 3.2.9 + 3.3.3 diff --git a/dxhy-customs/pom.xml b/dxhy-customs/pom.xml index bf6ef95a..400bed9a 100644 --- a/dxhy-customs/pom.xml +++ b/dxhy-customs/pom.xml @@ -111,7 +111,7 @@ com.dxhy.jxpt dxhy-oss - 3.2.9 + 3.3.3 com.alibaba.cloud diff --git a/dxhy-erp/pom.xml b/dxhy-erp/pom.xml index 550b4269..1341d782 100644 --- a/dxhy-erp/pom.xml +++ b/dxhy-erp/pom.xml @@ -107,7 +107,7 @@ com.dxhy.jxpt dxhy-oss - 3.2.9 + 3.3.3 com.twelvemonkeys.imageio diff --git a/dxhy-oss/README b/dxhy-oss/README new file mode 100644 index 00000000..e845566c --- /dev/null +++ b/dxhy-oss/README @@ -0,0 +1 @@ +README diff --git a/dxhy-oss/pom.xml b/dxhy-oss/pom.xml new file mode 100644 index 00000000..8d99d8d3 --- /dev/null +++ b/dxhy-oss/pom.xml @@ -0,0 +1,132 @@ + + + + com.dxhy + ofd + 3.2.1 + + 4.0.0 + + + com.dxhy.jxpt + dxhy-oss + 3.3.3 + jar + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + + org.projectlombok + lombok + + + cn.hutool + hutool-all + ${hutool.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + + com.aliyun.oss + aliyun-sdk-oss + 3.13.2 + + + com.jcraft + jsch + 0.1.55 + + + com.amazonaws + aws-java-sdk-s3 + 1.12.131 + + + + + + commons-net + commons-net + 3.6 + + + + org.apache.commons + commons-pool2 + 2.7.0 + + + + + io.minio + minio + 8.3.9 + + + org.apache.commons + commons-lang3 + + + + + + + + releases + releases + http://10.1.20.6:8081/nexus/content/repositories/releases/ + + + + snapshots + snapshots + http://10.1.20.6:8081/nexus/content/repositories/snapshots/ + + + + + + true + + 大象慧云 + Public Repositories + http://10.1.20.6:8081/nexus/content/groups/public/ + + + alimaven + aliyun maven + http://maven.aliyun.com/nexus/content/groups/public/ + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + UTF-8 + true + + + + + diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/config/OssConfig.java b/dxhy-oss/src/main/java/com/dxhy/oss/config/OssConfig.java new file mode 100644 index 00000000..c38d490e --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/config/OssConfig.java @@ -0,0 +1,154 @@ +package com.dxhy.oss.config; + +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.jcraft.jsch.ChannelSftp; + +import lombok.Data; + +/** + * @author jiaohongyang + */ +@Component +@Data +public class OssConfig { + + /** + * oss 服务类型 JD AL FTP + */ + @Value("${oss.ossType:FTP}") + public String ossType; + /** + * 阿里请求地址 + */ + @Value("${oss.endpointUrl:}") + public String endpointUrl; + /** + * 访问密钥 + */ + @Value("${oss.accessKeyId:}") + public String accessKeyId; + /** + * 访问密钥 + */ + @Value("${oss.accessKeySecret:}") + public String accessKeySecret; + + /** + * 京东云地域 + */ + @Value("${oss.region:}") + public String region; + /** + * 实例 + */ + @Value("${oss.bucketName:}") + public String bucketName; + + /** + * ftp上传的根路径 + */ + @Value("${ftp.connection.pathPrefix:}") + public String pathPrefix; + + /** + * ftp服务器地址 + */ + @Value("${ftp.connection.hostname:}") + public String hostname; + + /** + * ftp服务器端口 + */ + @Value("${ftp.connection.port:62236}") + public String port; + + /** + * ftp登录密码 + */ + @Value("${ftp.connection.password:}") + public String password; + + @Value("${ftp.connection.timeout:6000}") + public String timeout; + /** + * ftp登录账号 + */ + @Value("${ftp.connection.username:}") + public String username; + + @Value("${ftp.connection.localPathDefault:}") + public String localPathDefault; + + /** + * 临时路径 + */ + @Value("${ftp.connection.tempPath:}") + public String tempPath; + + /** + * ftp配置信息 + */ + @Value("${ftp.connection.size:2}") + public String pdfSize; + + /** + * 图片的最大大小 + */ + @Value("${oss.imageSize:10485760}") + public long imageSize; + + /** + * 其他文件的最大大小 + */ + @Value("${oss.fileSize:1073741824}") + public long fileSize; + + 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; + } + + } +} 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 new file mode 100644 index 00000000..2ca3c1d5 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/config/OssReturnConfig.java @@ -0,0 +1,23 @@ +package com.dxhy.oss.config; + +/** + * @author jiaohongyang(焦红阳) + * @date 2020-09-30 + */ +public interface OssReturnConfig { + String SUCCESS = "000000"; + + String ERROR_01 = "000001"; + + String ERROR_09 = "999999"; + + String JD = "JD"; + + String AL = "AL"; + + String FTP = "FTP"; + + String TOS = "TOS"; + + String MINIO = "MINIO"; +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/model/FileModel.java b/dxhy-oss/src/main/java/com/dxhy/oss/model/FileModel.java new file mode 100644 index 00000000..196e1b07 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/model/FileModel.java @@ -0,0 +1,19 @@ +package com.dxhy.oss.model; + +import lombok.Data; + +/** + * @author jiaohongyang(焦红阳) + * @date 2020-10-17 + */ +@Data +public class FileModel { + /** + * 编码 + */ + private String code; + /** + * 文件地址 + */ + private String filePath; +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/AliOssService.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/AliOssService.java new file mode 100644 index 00000000..801c4adc --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/AliOssService.java @@ -0,0 +1,41 @@ +package com.dxhy.oss.service; + +import com.dxhy.oss.model.FileModel; + +/** + * @author jiaohongyang + */ +public interface AliOssService { + /** + * 阿里云OSS文件存储 + * + * @param file 文件 + * @return 返回 + */ + FileModel uploadFile(String fileName, String file); + + /** + * 下载 + * + * @param fileName 文件名称 + * @param filePath 本地文件存储地址 + * @return 返回 + */ + FileModel downloadFile(String fileName, String filePath); + + /** + * 删除文件 + * + * @param file 文件名 + * @return 返回 + */ + FileModel deleteFile(String file); + + /** + * 生产文件下载地址 + * + * @param key 文件传输路径加名称 + * @return 返回下载地址 + */ + FileModel getUrl(String key); +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/FileService.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/FileService.java new file mode 100644 index 00000000..0514e03f --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/FileService.java @@ -0,0 +1,72 @@ +package com.dxhy.oss.service; + +import com.dxhy.oss.model.FileModel; + +/** + * @author jiaohongyang + */ +public interface FileService { + /** + * 文件上传 + * + * @param fileName 文件 ftp名称 + * @param originFileName 本地文件地址 + * @return 返回 + * @throws Exception 异常 + */ + FileModel uploadFile(String fileName, String originFileName) throws Exception; + + /** + * 文件下载 + * + * @param downloadFile 下载文件 + * @param saveFile 保存文件地址 + * @return 返回 + * @throws Exception 异常 + */ + + FileModel downFile(String downloadFile, String saveFile) throws Exception; + + + /** + * 生成文件下载地址 + * + * @param key 文件传输路径加名称 + * @return 返回文件下载地址 + */ + FileModel getUrl(String key); + + /** + * 删除文件 + * + * @param file 文件地址 + * @return 返回 + */ + FileModel deleteFile(String file); + + + /** + * 获取ftp 上传地址 + * + * @return 返回 + */ + String getPathPrefix(); + + /** + * 图片本地地址 + * + * @return 返回 + */ + String getLocalPathDefault(); + + /** + * 临时路径 + */ + String getTempPath(); + + /** + * PDF 上传文件大小 + */ + String getFtpPdfSize(); + +} 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 new file mode 100644 index 00000000..c82fe0fb --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/FtpService.java @@ -0,0 +1,353 @@ +package com.dxhy.oss.service; + +import cn.hutool.core.io.FileUtil; +import com.dxhy.oss.utils.SftpPool; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.SftpException; +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 java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +/** + * @author jiaohongyang + */ +@Slf4j +public class FtpService { + + private final SftpPool pool; + + public FtpService(SftpPool pool) { + this.pool = pool; + } + + /** + * 将输入流的数据上传到sftp作为文件。文件完整路径 = basePath+directory + * + * @param pathName ftp服务保存地址,完整路径 + * @param fileName 上传到ftp的文件名 + * @param originFileName 待上传文件的名称(绝对地址) + */ + + public boolean uploadFile(String pathName, String fileName, String originFileName) throws InterruptedException { + 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 static boolean uploadFile(FTPClient ftpClient, String serviceDec, String fileName, InputStream inputStream) { + try { + log.info("开始上传文件"); + ftpClient.setFileType(FTP.BINARY_FILE_TYPE); + createDirecroty(ftpClient, serviceDec); + ftpClient.makeDirectory(serviceDec); + ftpClient.changeWorkingDirectory(serviceDec); + ftpClient.storeFile(fileName, inputStream); + inputStream.close(); + ftpClient.logout(); + log.info("上传文件成功"); + } catch (Exception e) { + log.error("上传文件失败" + e); + } finally { + try { + if (ftpClient.isConnected()) { + ftpClient.disconnect(); + } + if (null != inputStream) { + inputStream.close(); + } + } catch (IOException e) { + log.error("上传文件失败" + e); + return false; + } + } + return true; + } + + private static boolean createDirecroty(FTPClient ftpClient, String remote) throws IOException { + boolean success = true; + String directory = remote + "/"; + // 如果远程目录不存在,则递归创建远程服务器目录 + if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(ftpClient, new String(directory))) { + int start = 0; + int end = 0; + if (directory.startsWith("/")) { + start = 1; + } else { + start = 0; + } + end = directory.indexOf("/", start); + String path = ""; + String paths = ""; + while (true) { + String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1"); + path = path + "/" + subDirectory; + if (!existFile(ftpClient, path)) { + if (makeDirectory(ftpClient, subDirectory)) { + changeWorkingDirectory(ftpClient, subDirectory); + } else { + log.info("创建目录[" + subDirectory + "]失败"); + changeWorkingDirectory(ftpClient, subDirectory); + } + } else { + changeWorkingDirectory(ftpClient, subDirectory); + } + + paths = paths + "/" + subDirectory; + start = end + 1; + end = directory.indexOf("/", start); + // 检查所有目录是否创建完毕 + if (end <= start) { + break; + } + } + } + return success; + } + + //改变目录路径 + private static boolean changeWorkingDirectory(FTPClient ftpClient, String directory) { + boolean flag = true; + try { + flag = ftpClient.changeWorkingDirectory(directory); + if (flag) { + log.info("进入文件夹" + directory + " 成功!"); + + } else { + log.info("进入文件夹" + directory + " 失败!开始创建文件夹"); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + return flag; + } + + //判断ftp服务器文件是否存在 + private static boolean existFile(FTPClient ftpClient, String path) throws IOException { + boolean flag = false; + FTPFile[] ftpFileArr = ftpClient.listFiles(path); + if (ftpFileArr.length > 0) { + flag = true; + } + return flag; + } + + //创建目录 + private static boolean makeDirectory(FTPClient ftpClient, String dir) { + boolean flag = true; + try { + flag = ftpClient.makeDirectory(dir); + if (flag) { + log.info("创建文件夹" + dir + " 成功!"); + + } else { + log.info("创建文件夹" + dir + " 失败!"); + } + } catch (Exception e) { + e.printStackTrace(); + } + return flag; + } + + /** + * 获取FTP某一特定目录下的所有文件名称 + * + * @param ftpClient 已经登陆成功的FTPClient + * @param ftpDirPath FTP上的目标文件路径 + */ + public static List getFileNameList(FTPClient ftpClient, String ftpDirPath) { + List list = new ArrayList(); + try { + if (ftpDirPath.startsWith("/") && ftpDirPath.endsWith("/")) { + // 通过提供的文件路径获取FTPFile对象列表 + FTPFile[] files = ftpClient.listFiles(ftpDirPath); + // 遍历文件列表,打印出文件名称 + for (int i = 0; i < files.length; i++) { + FTPFile ftpFile = files[i]; + // 此处只打印文件,未遍历子目录(如果需要遍历,加上递归逻辑即可) + if (ftpFile.isFile()) { +// log.info(ftpDirPath + ftpFile.getName()); + list.add(ftpFile.getName()); + } + } + log.info("当前FTP路径可用"); + } else { + log.info("当前FTP路径不可用"); + } + } catch (IOException e) { + log.error("错误" + e); + } + return list; + } + public File downloadFile(FTPClient ftpClient, String servicePath, String fileName, String localFilePath) { + String name = dowFile(ftpClient, servicePath, fileName, localFilePath); + if (name != null && !name.equals("")){ + return new File(fileName); + } + return null; + } + + private static String dowFile(FTPClient ftpClient, String servicePath, String fileName, String localFilePath) { + InputStream is = null; + FileOutputStream fos = null; + try { + ftpClient.enterLocalPassiveMode(); + is = ftpClient.retrieveFileStream(servicePath + fileName);// 获取ftp上的文件 + fos = new FileOutputStream(new File(localFilePath + fileName)); + // 文件读取方式一 + int i; + byte[] bytes = new byte[1024]; + while ((i = is.read(bytes)) != -1) { + fos.write(bytes, 0, i); + } + // 文件读取方式二 + //ftpClient.retrieveFile(ftpFilePath, new FileOutputStream(new File(localFilePath))); + ftpClient.completePendingCommand(); + log.info("FTP文件下载成功!"); + } catch (Exception e) { + log.error("FTP文件下载失败!" + e); + } finally { + try { + if (fos != null) fos.close(); + if (is != null) is.close(); + } catch (IOException e) { + log.error("下载流关闭失败" + e); + return null; + } + } + return localFilePath + fileName; + } + + 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/JdOssService.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/JdOssService.java new file mode 100644 index 00000000..d6a8d2d1 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/JdOssService.java @@ -0,0 +1,46 @@ +package com.dxhy.oss.service; + +import com.dxhy.oss.model.FileModel; + +/** + * @author jiaohongyang + */ +public interface JdOssService { + /** + * 阿里云OSS文件存储 + * + * @param file + * 文件 + * @return 返回 + */ + FileModel uploadFile(String fileName, String file); + + /** + * 下载 + * + * @param fileName + * 文件名称 + * @param filePath + * 本地文件存储地址 + * @return 返回 + */ + FileModel downloadFile(String fileName, String filePath); + + /** + * 生成文件下载地址 + * + * @param key + * 文件传输路径加名称 + * @return 返回文件下载地址 + */ + FileModel getUrl(String key); + + /** + * 删除文件 + * + * @param file + * 文件信息 + * @return 返回 + */ + FileModel deleteFile(String file); +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/AliOssServiceImpl.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/AliOssServiceImpl.java new file mode 100644 index 00000000..b5c6a21f --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/AliOssServiceImpl.java @@ -0,0 +1,186 @@ +package com.dxhy.oss.service.impl; + +import cn.hutool.core.io.FileUtil; +import com.aliyun.oss.OSS; +import com.aliyun.oss.model.GetObjectRequest; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.net.URL; +import java.util.Date; + +/** + * @author jiaohongyang + */ +@Service("aliOssService") +@Slf4j +public class AliOssServiceImpl implements AliOssService { + + private final OssConfig ossConfig; + + @Autowired + public AliOssServiceImpl(OssConfig ossConfig) { + this.ossConfig = ossConfig; + } + + /** + * 阿里云OSS文件存储 + * + * @param filePath 文件 + * @return 返回 + */ + @Override + public FileModel uploadFile(String fileName, String filePath) { + OSS ossClient = null; + FileModel fileModel; + + log.info("文件存储阿里OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), fileName); + try { + // 创建连接 + ossClient = + OssClientFactory.getInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()); + if (ossClient == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + + // 进行文件上传 + + ossClient.putObject(ossConfig.getBucketName(), fileName, new File(filePath)); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(fileName); + return fileModel; + } catch (Exception e) { + log.error("文件存储阿里OSS失败,异常:{}", e.getMessage()); + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + FileUtil.del(filePath); + } + } + + @Override + public FileModel getUrl(String key) { + OSS ossClient = null; + FileModel fileModel; + try { + ossClient = + OssClientFactory.getInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()); + if (ossClient == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + // 设置URL过期时间为10年 3600l* 1000*24*365*10 + Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24); + // 生成URL + URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), key, expiration); + if (url != null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(url.toString()); + return fileModel; + } + } catch (Exception e) { + e.printStackTrace(); + + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + + /** + * 下载 + * + * @param fileName 文件名称 + * @param filePath 本地文件存储地址 + * @return 返回 + */ + @Override + public FileModel downloadFile(String fileName, String filePath) { + log.info("下载文件阿里OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), fileName); + OSS ossClient = null; + FileModel fileModel; + try { + // 创建连接 + ossClient = + OssClientFactory.getInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()); + if (ossClient == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。 + ossClient.getObject(new GetObjectRequest(ossConfig.getBucketName(), fileName), new File(filePath)); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(filePath); + return fileModel; + } catch (Exception e) { + log.error("文件下载阿里OSS失败,异常:{}", e.getMessage()); + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + } + + /** + * 删除文件 + * + * @param file 文件名 + * @return 返回 + */ + @Override + public FileModel deleteFile(String file) { + log.info("文件删除阿里OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), file); + OSS ossClient = null; + FileModel fileModel; + try { + // 创建连接 + ossClient = + OssClientFactory.getInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()); + if (ossClient == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + ossClient.deleteObject(ossConfig.getBucketName(), file); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + return fileModel; + } catch (Exception e) { + log.error("文件删除阿里OSS失败,异常:{}", e.getMessage()); + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + } +} 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 new file mode 100644 index 00000000..ad62dea6 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/FileServiceImpl.java @@ -0,0 +1,195 @@ +package com.dxhy.oss.service.impl; + +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 lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; + +/** + * @author jiaohongyang + */ +@Slf4j +@Service("fileService") +public class FileServiceImpl implements FileService { + private final OssConfig ossConfig; + private final AliOssService aliOssService; + private final JdOssService jdOssService; + private final FtpService ftpService; + + @Autowired + public FileServiceImpl(OssConfig ossConfig, AliOssService aliOssService, JdOssService jdOssService, FtpService ftpService) { + this.ossConfig = ossConfig; + this.aliOssService = aliOssService; + this.jdOssService = jdOssService; + this.ftpService = ftpService; + } + + /** + * 文件上传 + * + * @param fileName 上传文件,路径+ 名称 + * @param originFileName 本地文件地址 + * @return 返回 + * @throws Exception 异常 + */ + @Override + public FileModel uploadFile(String fileName, String originFileName) throws Exception { + log.info("上传文件地址:{} , 本地存储文件地址:{}", fileName, originFileName); + FileModel fileModel; + if (OssReturnConfig.AL.equals(ossConfig.getOssType())) { + if (fileName.startsWith("/")) { + fileName = fileName.substring(1); + } + fileModel = aliOssService.uploadFile(fileName, originFileName); + + } else if (OssReturnConfig.JD.equals(ossConfig.getOssType())) { + if (fileName.startsWith("/")) { + fileName = fileName.substring(1); + } + fileModel = jdOssService.uploadFile(fileName, originFileName); + + } else if (OssReturnConfig.FTP.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 = ftpService.uploadFile(directory, downloadFileName, originFileName); + fileModel = new FileModel(); + fileModel.setFilePath(fileName); + if (b) { + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel.setCode(OssReturnConfig.ERROR_09); + } + + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + } + log.info("文件上传结果编码:{},地址信息返回:{}", fileModel.getCode(), fileModel.getFilePath()); + return fileModel; + } + + @Override + public FileModel downFile(String downloadFile, String saveFile) { + log.info("下载文件地址:{} , 本地存储文件地址:{}", downloadFile, saveFile); + // 获取下载文件存储路径 ,路径不存在则创建路径 + File file = new File(saveFile); + String path = file.getParent(); + FileUtil.mkdir(path); + FileModel fileModel; + if (OssReturnConfig.AL.equals(ossConfig.getOssType())) { + if (downloadFile.startsWith("/")) { + downloadFile = downloadFile.substring(1); + } + fileModel = aliOssService.downloadFile(downloadFile, saveFile); + } else if (OssReturnConfig.JD.equals(ossConfig.getOssType())) { + if (downloadFile.startsWith("/")) { + downloadFile = downloadFile.substring(1); + } + fileModel = jdOssService.downloadFile(downloadFile, saveFile); + } else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { + String directory = downloadFile.substring(0, downloadFile.lastIndexOf("/")); + File directoryFile = new File(downloadFile); + String downloadFileName = directoryFile.getName(); + boolean b = ftpService.downloadFile(directory, downloadFileName, path); + fileModel = new FileModel(); + fileModel.setFilePath(saveFile); + if (b) { + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel.setCode(OssReturnConfig.ERROR_09); + } + + + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + } + log.info("文件下载结果编码:{},地址信息返回:{}", fileModel.getCode(), fileModel.getFilePath()); + return fileModel; + } + + + @Override + public FileModel getUrl(String key) { + FileModel fileModel; + log.info("生成文件下载地址:{} ", key); + if (OssReturnConfig.AL.equals(ossConfig.getOssType())) { + fileModel = aliOssService.getUrl(key); + } else if (OssReturnConfig.JD.equals(ossConfig.getOssType())) { + fileModel = jdOssService.getUrl(key); + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + } + log.info("生成文件下载地址结果编码:{},地址链接返回:{}", fileModel.getCode(), fileModel.getFilePath()); + return fileModel; + } + + @Override + public FileModel deleteFile(String path) { + log.info("删除文件信息:{} ", path); + FileModel fileModel; + if (OssReturnConfig.AL.equals(ossConfig.getOssType())) { + if (path.startsWith("/")) { + path = path.substring(1); + } + fileModel = aliOssService.deleteFile(path); + } else if (OssReturnConfig.JD.equals(ossConfig.getOssType())) { + if (path.startsWith("/")) { + path = path.substring(1); + } + fileModel = jdOssService.deleteFile(path); + } else if (OssReturnConfig.FTP.equals(ossConfig.getOssType())) { + File file = new File(path); + boolean b = ftpService.deleteFile(file.getParent(), file.getName()); + if (b) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_01); + } + } else { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + } + log.info("删除文件信息返回结果编码:{}", fileModel.getCode()); + return fileModel; + } + + @Override + public String getPathPrefix() { + return ossConfig.getPathPrefix(); + } + + @Override + public String getLocalPathDefault() { + return ossConfig.getLocalPathDefault(); + } + + @Override + public String getTempPath() { + return ossConfig.getTempPath(); + } + + /** + * PDF 上传文件大小 + */ + @Override + public String getFtpPdfSize() { + return ossConfig.getPdfSize(); + } +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/JdOssServiceImpl.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/JdOssServiceImpl.java new file mode 100644 index 00000000..349d123f --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/JdOssServiceImpl.java @@ -0,0 +1,213 @@ +package com.dxhy.oss.service.impl; + +import cn.hutool.core.io.FileUtil; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; +import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.S3ObjectInputStream; +import com.dxhy.oss.config.OssConfig; +import com.dxhy.oss.config.OssReturnConfig; +import com.dxhy.oss.model.FileModel; +import com.dxhy.oss.service.JdOssService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Date; + +/** + * @author jiaohongyang + */ +@Service("jdOssService") +@Slf4j +public class JdOssServiceImpl implements JdOssService { + private final OssConfig ossConfig; + + @Autowired + public JdOssServiceImpl(OssConfig ossConfig) { + this.ossConfig = ossConfig; + } + + /** + * 京东云OSS文件存储 + * + * @param filePath 文件 + * @return 返回 + */ + @Override + public FileModel uploadFile(String fileName, String filePath) { + FileModel fileModel; + AmazonS3 jdInstance = null; + + log.info("文件存储京东OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), fileName); + try { + // 创建连接 + jdInstance = OssClientFactory.getJdInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), + ossConfig.getAccessKeySecret(), ossConfig.getRegion()); + if (jdInstance == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + + // 进行文件上传 + jdInstance.putObject(ossConfig.getBucketName(), fileName, new File(filePath)); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(fileName); + return fileModel; + } catch (Exception e) { + log.error("文件存储京东OSS失败,异常:{}", e.getMessage()); + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + if (jdInstance != null) { + jdInstance.shutdown(); + } + FileUtil.del(filePath); + } + } + + /** + * 下载 + * + * @param fileName 文件名称 + * @param filePath 本地文件存储地址 + * @return 返回 + */ + @Override + public FileModel downloadFile(String fileName, String filePath) { + log.info("下载文件京东OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), fileName); + AmazonS3 jdInstance = null; + S3ObjectInputStream s3is = null; + FileOutputStream fos = null; + FileModel fileModel; + try { + // 创建连接 + jdInstance = OssClientFactory.getJdInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), + ossConfig.getAccessKeySecret(), ossConfig.getRegion()); + if (jdInstance == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。 + S3Object object = jdInstance.getObject(ossConfig.getBucketName(), fileName); + s3is = object.getObjectContent(); + fos = new FileOutputStream(filePath); + byte[] readBuf = new byte[1024]; + int readLen = 0; + while ((readLen = s3is.read(readBuf)) > 0) { + fos.write(readBuf, 0, readLen); + } + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(filePath); + return fileModel; + } catch (Exception e) { + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + try { + if (s3is != null) { + s3is.close(); + } + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + if (jdInstance != null) { + jdInstance.shutdown(); + } + } + } + + @Override + public FileModel getUrl(String key) { + log.info("生成文件下载地址京东OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), key); + AmazonS3 jdInstance = null; + FileModel fileModel; + try { + // 创建连接 + jdInstance = OssClientFactory.getJdInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), + ossConfig.getAccessKeySecret(), ossConfig.getRegion()); + if (jdInstance == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + // 设置URL过期时间为10年 3600l* 1000*24*365*10 + Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 2); + GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(ossConfig.getBucketName(), key); + request.setExpiration(expiration); + URL url = jdInstance.generatePresignedUrl(request); + if (url != null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + fileModel.setFilePath(url.toString()); + return fileModel; + } + + } catch (Exception e) { + e.printStackTrace(); + log.error("文件下载京东OSS失败,异常:{}", e.getMessage()); + } finally { + if (jdInstance != null) { + jdInstance.shutdown(); + } + } + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + + } + + /** + * 删除文件 + * + * @param file 文件名 + * @return 返回 + */ + @Override + public FileModel deleteFile(String file) { + log.info("文件删除京东云OSS,存储目录:{} , 存储文件名:{} ", ossConfig.getBucketName(), file); + AmazonS3 jdInstance = null; + FileModel fileModel; + try { + // 创建连接 + // 创建连接 + jdInstance = OssClientFactory.getJdInstance(ossConfig.getEndpointUrl(), ossConfig.getAccessKeyId(), + ossConfig.getAccessKeySecret(), ossConfig.getRegion()); + if (jdInstance == null) { + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } + jdInstance.deleteObject(ossConfig.getBucketName(), file); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.SUCCESS); + return fileModel; + } catch (Exception e) { + log.error("文件删除京东云OSS失败,异常:{}", e.getMessage()); + e.printStackTrace(); + fileModel = new FileModel(); + fileModel.setCode(OssReturnConfig.ERROR_09); + return fileModel; + } finally { + if (jdInstance != null) { + jdInstance.shutdown(); + } + } + } +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/OssClientFactory.java b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/OssClientFactory.java new file mode 100644 index 00000000..333d6d99 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/service/impl/OssClientFactory.java @@ -0,0 +1,55 @@ +package com.dxhy.oss.service.impl; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.amazonaws.ClientConfiguration; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3Client; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Scope; + +/** + * @author jiaohongyang + */ +@Slf4j +public class OssClientFactory { + + private OssClientFactory() { + } + + /** + * 创建连接 + */ + @Bean + @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static OSS getInstance(String endpointUrl, String accessKeyId, String accessKeySecret) { + return new OSSClientBuilder().build(endpointUrl, accessKeyId, accessKeySecret); + } + + + @Bean + @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static AmazonS3 getJdInstance(String endpointUrl, String accessKeyId, String accessKeySecret, + String region) { + ClientConfiguration config = new ClientConfiguration(); + + AwsClientBuilder.EndpointConfiguration endpointConfig = + new AwsClientBuilder.EndpointConfiguration(endpointUrl, region); + + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKeyId, accessKeySecret); + AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials); + + return AmazonS3Client.builder().withEndpointConfiguration(endpointConfig).withClientConfiguration(config) + .withCredentials(awsCredentialsProvider).disableChunkedEncoding().withPathStyleAccessEnabled(true) + .build(); + } + + +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/FileTypeUtils.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/FileTypeUtils.java new file mode 100644 index 00000000..593c5ae8 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/FileTypeUtils.java @@ -0,0 +1,60 @@ +package com.dxhy.oss.utils; + +import cn.hutool.core.io.FileTypeUtil; + +import java.io.InputStream; + +/** + * 文件类型工具类 + * TODO 其中只是定义了部分文件格式,有缺失的自己添加 + */ +public class FileTypeUtils { + + private final static String IMAGE_TYPE = "image/"; + private final static String AUDIO_TYPE = "audio/"; + private final static String VIDEO_TYPE = "video/"; + private final static String APPLICATION_TYPE = "application/"; + private final static String TXT_TYPE = "text/"; + + public static String getFileType(InputStream fileInputStream) { + String type = null; + try { + + type = FileTypeUtil.getType(fileInputStream); + if (type.equalsIgnoreCase("JPG") || type.equalsIgnoreCase("JPEG") + || type.equalsIgnoreCase("GIF") || type.equalsIgnoreCase("PNG") + || type.equalsIgnoreCase("BMP") || type.equalsIgnoreCase("PCX") + || type.equalsIgnoreCase("TGA") || type.equalsIgnoreCase("PSD") + || type.equalsIgnoreCase("TIFF")) { + return IMAGE_TYPE + type; + } + if (type.equalsIgnoreCase("mp3") || type.equalsIgnoreCase("OGG") + || type.equalsIgnoreCase("WAV") || type.equalsIgnoreCase("REAL") + || type.equalsIgnoreCase("APE") || type.equalsIgnoreCase("MODULE") + || type.equalsIgnoreCase("MIDI") || type.equalsIgnoreCase("VQF") + || type.equalsIgnoreCase("CD")) { + return AUDIO_TYPE + type; + } + if (type.equalsIgnoreCase("mp4") || type.equalsIgnoreCase("avi") + || type.equalsIgnoreCase("MPEG-1") || type.equalsIgnoreCase("RM") + || type.equalsIgnoreCase("ASF") || type.equalsIgnoreCase("WMV") + || type.equalsIgnoreCase("qlv") || type.equalsIgnoreCase("MPEG-2") + || type.equalsIgnoreCase("MPEG4") || type.equalsIgnoreCase("mov") + || type.equalsIgnoreCase("3gp")) { + return VIDEO_TYPE + type; + } + if (type.equalsIgnoreCase("doc") || type.equalsIgnoreCase("docx") + || type.equalsIgnoreCase("ppt") || type.equalsIgnoreCase("pptx") + || type.equalsIgnoreCase("xls") || type.equalsIgnoreCase("xlsx") + || type.equalsIgnoreCase("zip") || type.equalsIgnoreCase("jar")) { + return APPLICATION_TYPE + type; + } + if (type.equalsIgnoreCase("txt")) { + return TXT_TYPE + type; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpConfig.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpConfig.java new file mode 100644 index 00000000..9dba4130 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpConfig.java @@ -0,0 +1,31 @@ +package com.dxhy.oss.utils; + +import com.dxhy.oss.service.FtpService; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +// ftp配置 +@Configuration +@EnableConfigurationProperties(SftpProperties.class) +public class SftpConfig { + + // 工厂 + @Bean + public SftpFactory sftpFactory(SftpProperties properties) { + return new SftpFactory(properties); + } + + // 连接池 + @Bean + public SftpPool sftpPool(SftpFactory sftpFactory) { + return new SftpPool(sftpFactory); + } + + // 辅助类 + @Bean + public FtpService ftpService(SftpPool sftpPool) { + return new FtpService(sftpPool); + } + +} \ No newline at end of file diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpFactory.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpFactory.java new file mode 100644 index 00000000..8695b5d6 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpFactory.java @@ -0,0 +1,96 @@ +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.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPReply; +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 SftpFactory extends BasePooledObjectFactory { + + private SftpProperties ossConfig; + + public SftpFactory(SftpProperties 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); + } + } + + public FTPClient createFtp() throws SftpPoolException{ + FTPClient ftpClient = null; + try { + ftpClient = new FTPClient(); + ftpClient.setControlEncoding("UTF-8");// 中文支持 + ftpClient.setConnectTimeout(1000 * 30);//设置连接超时时间 + ftpClient.connect(ossConfig.getHostname(), Integer.valueOf(ossConfig.getPort()));// 连接FTP服务器 + ftpClient.login(ossConfig.getUsername(), ossConfig.getPassword());// 登陆FTP服务器 + // 设置文件类型为二进制(如果从FTP下载或上传的文件是压缩文件的时候,不进行该设置可能会导致获取的压缩文件解压失败) + ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); +// ftpClient.enterLocalPassiveMode();//开启被动模式,否则文件上传不成功,也不报错 + if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { + log.info("连接FTP失败,用户名或密码错误。"); + ftpClient.disconnect(); + } else { + log.info("FTP连接成功!"); + } + } catch (Exception e) { + log.info("登陆FTP失败,请检查FTP相关配置信息是否正确!" + e); + return null; + } + return ftpClient; + } + + @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/SftpPool.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpPool.java new file mode 100644 index 00000000..f14f3442 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpPool.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 SftpPool { + + private GenericObjectPool pool; + + public SftpPool(SftpFactory 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/SftpPoolException.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpPoolException.java new file mode 100644 index 00000000..7ed1f109 --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpPoolException.java @@ -0,0 +1,15 @@ +package com.dxhy.oss.utils; + + +/** + * @author jiaohongyang + * @date 2019年3月26日 下午5:57:26 + */ + +public class SftpPoolException extends Exception { + public SftpPoolException(String message, Exception e) { + super(message, e); + } + + +} diff --git a/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpProperties.java b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpProperties.java new file mode 100644 index 00000000..3ad51d4a --- /dev/null +++ b/dxhy-oss/src/main/java/com/dxhy/oss/utils/SftpProperties.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 SftpProperties { + + 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 diff --git a/dxhy-oss/src/test/java/com/dxhy/DxhyOssApplication.java b/dxhy-oss/src/test/java/com/dxhy/DxhyOssApplication.java new file mode 100644 index 00000000..23ddaada --- /dev/null +++ b/dxhy-oss/src/test/java/com/dxhy/DxhyOssApplication.java @@ -0,0 +1,13 @@ +package com.dxhy; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan("com.dxhy.*") +public class DxhyOssApplication { + public static void main(String[] args) { + SpringApplication.run(DxhyOssApplication.class, args); + } +} diff --git a/dxhy-oss/src/test/java/com/dxhy/OfdHandle.java b/dxhy-oss/src/test/java/com/dxhy/OfdHandle.java new file mode 100644 index 00000000..36b80b49 --- /dev/null +++ b/dxhy-oss/src/test/java/com/dxhy/OfdHandle.java @@ -0,0 +1,40 @@ +package com.dxhy; + + +import com.dxhy.oss.model.FileModel; +import com.dxhy.oss.service.FileService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; + +/** + * @author user + */ +@SuppressWarnings("FieldCanBeLocal") +@Slf4j +public class OfdHandle extends Thread { + + private final File file; + + @Autowired + private FileService fileService; + + public OfdHandle(File file) { + this.file = file; + + } + + @Override + public void run() { + + fileService = (FileService) SpringContextUtils.getBean("fileService"); + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.uploadFile(file.getPath(), file.getPath()); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("文件上传返回结果:" + fileModel.getCode() + " " + fileModel.getFilePath()); + } +} diff --git a/dxhy-oss/src/test/java/com/dxhy/OssTest.java b/dxhy-oss/src/test/java/com/dxhy/OssTest.java new file mode 100644 index 00000000..73f9911d --- /dev/null +++ b/dxhy-oss/src/test/java/com/dxhy/OssTest.java @@ -0,0 +1,127 @@ +package com.dxhy; + +import java.io.File; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Resource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.dxhy.oss.model.FileModel; +import com.dxhy.oss.service.FileService; + +import cn.hutool.core.io.FileUtil; + +/** + * @author jiaohongyang(焦红阳) + * @date 2020-09-30 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = DxhyOssApplication.class) +public class OssTest { + @Resource + private FileService fileService; + + @Test + public void ossUploadTest() { + String fileName = "/GYL/YONGHUI/2022/09/08/update.zip"; + String originFileName = "/Users/jiaohongyang/product/project/project/jxpt/ofd/pdf/update.zip"; + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.uploadFile(fileName, originFileName); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("文件上传返回结果:" + fileModel.getCode() + " " + fileModel.getFilePath()); + + } + + @Test + public void ossGylUploadTest() { + String fileName = "/GYL/DUODIAN/2022/12/07/update.zip"; + String originFileName = "/Users/jiaohongyang/product/project/project/jxpt/ofd/pdf/update.zip"; + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.uploadFile(fileName, originFileName); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("文件上传返回结果:" + fileModel.getCode() + " " + fileModel.getFilePath()); + + } + + @Test + public void ossGylSdlpUploadTest() { + String fileName = "/GYL/SDLP/2022/09/20/51发票助手_local_J_1.4.8.exe"; + String originFileName = "/Users/jiaohongyang/product/project/project/jxpt/ofd/pdf/51发票助手_local_J_1.4.8.exe"; + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.uploadFile(fileName, originFileName); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("文件上传返回结果:" + fileModel.getCode() + " " + fileModel.getFilePath()); + + } + + @Test + public void ossDownloadTest() { + String downloadFile = "/jxfp/pdf/2022/1111/dxhy-admin.jar"; + // String downloadFile = "/jxfp/excel/2020/10/12/1282510566564315137_进项票据采集_2020-10-12_1602489969696.xlsx"; + String saveFile = "/Users/jiaohongyang/product/project/project/jxpt/ofd/pdf/dxhy-admin.jar"; + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.downFile(downloadFile, saveFile); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("文件下载返回结果" + fileModel.getCode() + " " + fileModel.getFilePath()); + } + + @Test + public void ossgetUrlTest() { + String key = "/GYL/SDLP/2022/09/14/供应链协同开票助手-v1.1.0.1.20220914-x86_Setup.zip"; + FileModel fileModel = fileService.getUrl(key); + System.out.println(fileModel.getCode() + " " + fileModel.getFilePath()); + + } + + @Test + public void ossDeleteTest() { + String downloadFile = "GYL/DUODIAN/2022/12/01/20221201(1.1.0.2).zip"; + FileModel fileModel = new FileModel(); + try { + fileModel = fileService.deleteFile(downloadFile); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("文件删除返回结果" + fileModel.getCode()); + + } + + @Test + public void ossPush() { + String path = "/Volumes/product/PDF/"; + try { + File[] ls = FileUtil.ls(path); + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2000, 10000, 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(ls.length), r -> new Thread(r, "oss推送-" + r.hashCode())); + for (File file : ls) { + if (!threadPoolExecutor.isShutdown()) { + threadPoolExecutor.execute(new OfdHandle(file)); + } + } + threadPoolExecutor.shutdown(); + threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS); + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/dxhy-oss/src/test/java/com/dxhy/SpringContextUtils.java b/dxhy-oss/src/test/java/com/dxhy/SpringContextUtils.java new file mode 100644 index 00000000..37d9358c --- /dev/null +++ b/dxhy-oss/src/test/java/com/dxhy/SpringContextUtils.java @@ -0,0 +1,43 @@ +package com.dxhy; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring Context 工具类 + * + * @author jiaohongyang + */ +@Component + +public class SpringContextUtils implements ApplicationContextAware { + public static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static T getBean(String name, Class requiredType) { + return applicationContext.getBean(name, requiredType); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) { + return applicationContext.getType(name); + } + +} diff --git a/dxhy-oss/src/test/resources/application.yml b/dxhy-oss/src/test/resources/application.yml new file mode 100644 index 00000000..a56547cc --- /dev/null +++ b/dxhy-oss/src/test/resources/application.yml @@ -0,0 +1,48 @@ +#oss: +# ossType: AL +# endpointUrl: http://oss-accelerate.aliyuncs.com +# accessKeyId: LTAI4G6XxTTwUzcY3ByWa6Yb +# accessKeySecret: kkgPJ4DIvkOcvfZPl4BE1FVqyQlPiq +# region: +# bucketName: jiaohongyang +#oss: +# ossType: JD +# endpointUrl: https://storage.jd.local +# accessKeyId: bfac05320eaf11cc80cf1823e4fb87d98523fc94 +# accessKeySecret: 70ec454ffb302043a7837417e0909e12d1288d0b +# region: cn-north-1 +# bucketName: input-tax-invoice +#oss: +# ossType: AL +# endpointUrl: http://oss-cn-beijing-internal.aliyuncs.com +# accessKeyId: LTAI4GHGCEiWsXxTZ651wV22 +# accessKeySecret: hTXim31f5JmIMz3rcj7WIopKAUscsE +# region: +# bucketName: guowangtest +#oss: +# ossType: MINIO +# endpointUrl: http://10.1.2.107:9000 +# accessKeyId: minioadmin +# accessKeySecret: minioadmin +# region: +# bucketName: jxpt +oss: + ossType: JD + endpointUrl: https://s3.cn-north-1.jdcloud-oss.com + accessKeyId: 4B2A089EA1C8F776357A15948DBCA363 + accessKeySecret: 570296481BA33BFC4A8C9EEB5E00652A + region: cn-north-1 + bucketName: jxdownload +ftp: + connection: + hostname: 10.1.2.87 + username: dxhy1 + password: dxhy + port: 62236 + timeout: 60000 + pathPrefix: /jxfp/excel/ + # 连接池参数 + pool: + max-total: 10 + max-idle: 10 + min-idle: 5 diff --git a/dxhy-portrait/pom.xml b/dxhy-portrait/pom.xml index b6f5bb4f..d8a40f64 100644 --- a/dxhy-portrait/pom.xml +++ b/dxhy-portrait/pom.xml @@ -106,7 +106,7 @@ com.dxhy.jxpt dxhy-oss - 3.2.9 + 3.3.3 com.alibaba.cloud diff --git a/dxhy-sign/pom.xml b/dxhy-sign/pom.xml index 7d1b45e3..5d58f456 100644 --- a/dxhy-sign/pom.xml +++ b/dxhy-sign/pom.xml @@ -118,7 +118,7 @@ com.dxhy.jxpt dxhy-oss - 3.2.9 + 3.3.3 com.alibaba.cloud diff --git a/pom.xml b/pom.xml index 1886e621..db1f034d 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ dxhy-admin dxhy-gateway dxhy-base + dxhy-oss dxhy-core dxhy-erp dxhy-extend