diff --git a/ruoyi-modules/ruoyi-file/pom.xml b/ruoyi-modules/ruoyi-file/pom.xml index 9647f150..aef3ed06 100644 --- a/ruoyi-modules/ruoyi-file/pom.xml +++ b/ruoyi-modules/ruoyi-file/pom.xml @@ -90,7 +90,7 @@ com.aliyun.oss aliyun-sdk-oss - 3.5.0 + 3.10.0 diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FtpConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FtpConfig.java index a4d2abdf..a28f0924 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FtpConfig.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FtpConfig.java @@ -45,6 +45,12 @@ public class FtpConfig { * vsftpd:使用的 系统用户的目录,这里往往都是不是根目录,如:/home/ftpuser/ */ private String rootFtpPath = ""; + /** + * 上传文件对外访问的地址; + * hostname经常是内网ip; 不带https or 不待 http + * eg: https://www.ourslook.com/ + */ + private String domain; public String getHostName() { return hostName; @@ -85,4 +91,12 @@ public class FtpConfig { public void setRootFtpPath(String rootFtpPath) { this.rootFtpPath = rootFtpPath; } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java index dd69cf88..7756a782 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.file.service; +import cn.hutool.core.io.FileUtil; import cn.hutool.extra.spring.SpringUtil; import com.aliyun.oss.*; import com.aliyun.oss.model.*; @@ -9,12 +10,12 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; -import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.util.*; @@ -41,6 +42,7 @@ import java.util.concurrent.TimeUnit; * @date 2019/8/6 19:02 * //@see AliyunMsgUtil */ +@Primary @Service public class AliyunOssDsfServiceImpl implements IDfsService { private static final Logger log = LoggerFactory.getLogger(AliyunOssDsfServiceImpl.class); @@ -64,7 +66,7 @@ public class AliyunOssDsfServiceImpl implements IDfsService { //key: 这里不能以/开头 String newName = validateModule(file, null); //key: 这里不能以/开头 - String requestKey = "upload/" + "/" + newName; + String requestKey = "upload/" + StringUtils.defaultString(modules, "default") + "/" + newName; //这里增加一个前缀区分一下是测试环境还是正式环境 boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); if (!isProd) { @@ -151,6 +153,7 @@ public class AliyunOssDsfServiceImpl implements IDfsService { * 转换url * * @param filePath https://hiber2019.oss-cn-shanghai.aliyuncs.com/upload/default/20190806202208849_jvs5g.png + * eg2: 上传之后的格式:https://react-yuebaoxiao-pro.oss-cn-shanghai.aliyuncs.com/dev//upload/default/20210717-a77f6bb0-7b0a-4ef1-a839-f8e8aca469b8.jpeg * @return upload/default/20190806202208849_jvs5g.png */ private String getStorePath(String filePath) { @@ -159,16 +162,20 @@ public class AliyunOssDsfServiceImpl implements IDfsService { String domain = aliyunOssConfig.getDomain(); String publicPath1 = "https://" + bucketName + "." + endPoint + "/"; String publicPath2 = "http://" + bucketName + "." + endPoint + "/"; - String publicPath3 = "https://" + domain + "/"; - String publicPath4 = "http://" + domain + "/"; - //String publicPath5 = ServletCacheUtils.getInstance().getHttpRootPath(); - + String publicPath3 = domain + "/"; + String oldPath = filePath; filePath = filePath.replace(publicPath1, ""); filePath = filePath.replace(publicPath2, ""); filePath = filePath.replace(publicPath3, ""); - filePath = filePath.replace(publicPath4, ""); - //filePath = filePath.replace(publicPath5, ""); + + if (oldPath.equals(filePath)) { + // 使用方式2 + String group = "upload"; + // 获取group起始位置 + int pathStartPos = filePath.indexOf(group) + 1; + filePath = filePath.substring(pathStartPos, filePath.length()); + } return filePath; } @@ -178,15 +185,21 @@ public class AliyunOssDsfServiceImpl implements IDfsService { * @param picturePath 文件的访问路径,access url * @param file 等待上传的文件 * @return picturePath 上传文件的相对路径 + * 官网:https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.948.64b014a0QG5CsQ * demo https://github.com/aliyun/aliyun-oss-java-sdk/blob/master/src/samples/UploadSample.java */ private String ossUploadFileSmall(String endpoint, String picturePath, MultipartFile file) throws IOException { OSS ossClient = new OSSClientBuilder().build(endpoint, aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); - try { // 上传文件 (上传文件流的形式) PutObjectResult putResult = ossClient.putObject(aliyunOssConfig.getBucketName(), picturePath, file.getInputStream()); } catch (OSSException oe) { + // 使用OSS的API接口或SDK时提示“SignatureDoesNotMatch”签名相关的报错 + // SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method + // https://help.aliyun.com/knowledge_detail/39637.html?spm=5176.21213303.J_6028563670.7.74bc3edaCiPpyc&scm=20140722.S_help%40%40%E7%9F%A5%E8%AF%86%E7%82%B9%40%4039637.S_hot.ID_39637-OR_s%2Bhelpproduct-V_1-P0_0 + if ("SignatureDoesNotMatch".equalsIgnoreCase(oe.getErrorCode())) { + log.error("SignatureDoesNotMatch access-key-secret错误; 或者 key 和 secret不匹配。"); + } log.error("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); log.error("Error Message: {}", oe.getErrorMessage()); @@ -492,13 +505,14 @@ public class AliyunOssDsfServiceImpl implements IDfsService { } while (objectListing.isTruncated()); client.shutdown(); - if (size > (1024 * 1024)) { + /*if (size > (1024 * 1024)) { result = (new BigDecimal((double) size / 1024 / 1024)).setScale(2, BigDecimal.ROUND_HALF_UP) + "GB"; } else if (size > 1024) { result = (new BigDecimal((double) size / 1024).setScale(2, BigDecimal.ROUND_HALF_UP)) + "MB"; } else { result = size + "KB"; - } + }*/ + result = FileUtil.readableFileSize(size); return result; } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java index 8122412a..8f035e5c 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java @@ -4,7 +4,9 @@ import cn.hutool.extra.ftp.Ftp; import cn.hutool.extra.ftp.FtpMode; import com.ruoyi.common.core.exception.CustomException; import com.ruoyi.file.config.FtpConfig; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -19,7 +21,6 @@ import java.io.IOException; public class FtpFileServiceImpl implements IDfsService { @Autowired private FtpConfig ftpConfig; - public static final String ACCESS_PREFIX = ""; @Override public String uploadFile(MultipartFile file) throws Exception { @@ -28,20 +29,26 @@ public class FtpFileServiceImpl implements IDfsService { @Override public String uploadFile(MultipartFile file, String modules) throws Exception { - String fileName = "upload/" + validateModule(file, modules); + String fileName = validateModule(file, modules); + + modules = StringUtils.defaultString(modules, "default"); + String picturePath = "/upload/" + modules; Ftp ftp = null; try { ftp = new Ftp(ftpConfig.getHostName(), ftpConfig.getPort(), ftpConfig.getUserName(), ftpConfig.getPassword()); - ftp.cd(""); - ftp.setMode(FtpMode.Passive); - ftp.upload("", fileName, file.getInputStream()); + ftp.setBackToPwd(true); + ftp.cd("/"); + // 主要是主动模式还是被动 + ftp.setMode(FtpMode.Active); + ftp.upload(picturePath, fileName, file.getInputStream()); } finally { if (ftp != null) { ftp.close(); } } - return ftpConfig.getHostName() + "/" + fileName; + String url = ftpConfig.getDomain() + "/" + picturePath + "/" + fileName; + return url.replace("//", "/"); } @Override @@ -49,6 +56,8 @@ public class FtpFileServiceImpl implements IDfsService { Ftp ftp = null; try { ftp = new Ftp(ftpConfig.getHostName(), ftpConfig.getPort(), ftpConfig.getUserName(), ftpConfig.getPassword()); + // 主要是主动模式还是被动 + ftp.setMode(FtpMode.Active); String storePath = getStorePath(fileUrl); return ftp.delFile(storePath); } finally { @@ -67,14 +76,15 @@ public class FtpFileServiceImpl implements IDfsService { throw new CustomException("fpt-获取文件占用空间功能,敬请期待"); } + /** + * 转换url,为原始的key + * + * @param filePath https://test53.ourslook.com/upload/default/20210717-e646d18a-e405-4d09-a62a-11e58b67b48d.jpeg + * @return upload/default/20210717-e646d18a-e405-4d09-a62a-11e58b67b48d.jpeg + */ private String getStorePath(String filePath) { - int groupStartPos = -1; - if ((groupStartPos = filePath.indexOf(ACCESS_PREFIX) + ACCESS_PREFIX.length()) + 1 == 0) { - groupStartPos = 0; - //throw new RrException("解析文件路径错误,被解析路径url没有" + Constant.SERVIER_NAME_SUFFIX + ",当前解析路径为".concat(filePath)); - } - // 获取group起始位置 - String groupAndPath = filePath.substring(groupStartPos); - return groupAndPath + ""; + // 使用方式1 + String domain = ftpConfig.getDomain(); + return filePath.replace(domain, ""); } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java index 9a21c902..31041825 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java @@ -70,7 +70,6 @@ public interface IDfsService * @param file 文件 * @param modules 模块,这里作为上传的文件夹使用;eg: 项目中有banner、video、music、txt、product、default 多个模块,不同模块存放到不同文件夹中; * @return 新的系统生成的文件名称 - * @throws InvalidExtensionException */ default String validateModule(MultipartFile file, String modules) throws InvalidExtensionException { Objects.requireNonNull(file, "文件不能为空!"); @@ -91,6 +90,6 @@ public interface IDfsService // 3、文件大小校验 assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - return modules + "/" + extractFilename(file); + return extractFilename(file); } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalFileServiceImpl.java index 03bf028e..505539c9 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalFileServiceImpl.java @@ -3,7 +3,6 @@ package com.ruoyi.file.service; import cn.hutool.core.io.FileUtil; import com.ruoyi.common.core.exception.CustomException; import com.ruoyi.file.config.LocalFileConfig; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -17,7 +16,6 @@ import java.io.File; * * @author ruoyi */ -@Primary @Service public class LocalFileServiceImpl implements IDfsService { diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java index 02eb1cd2..a6ba763a 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java @@ -88,7 +88,9 @@ public class FileUploadUtils { String fileName = file.getOriginalFilename(); String extension = getExtension(file); - fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + //fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + // 文件名称中,不要带有 路径分割符号 + fileName = DateUtils.dateTime() + "-" + IdUtils.fastUUID() + "." + extension; return fileName; } diff --git a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml index 8c5d187d..899210bf 100644 --- a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml @@ -33,6 +33,14 @@ file: prefix: /statics path: D:/ruoyi/uploadPath +# 文件服务器之2 ftp +ftp: + host-name: 118.31.2.53 + port: 21 + user-name: lanjinjun + password: + domain: https://test53.ourslook.com + # 文件服务器之3 FastDFS配置 fdfs: domain: http://8.129.231.12 @@ -46,5 +54,12 @@ minio: accessKey: D99KGE6ZTQXSATTJWU24 secretKey: QyVqGnhIQQE734UYSUFlGOZViE6+ZlDEfUG3NjhJ bucketName: neusoft-appt - #regex: .*appt-file/ - #encryptFlag: true + +# 文件服务器之5 aliyun oss +aliyun-oss: + access-key-id: LTAI4GDQSbwgmbsRxxbDXnKT + access-key-secret: I1xYosCsIf4YgHeFbWUOU4faImeWD2 + bucket-name: react-yuebaoxiao-pro + endpoint: oss-cn-shanghai.aliyuncs.com + domain: https://react-yuebaoxiao-pro.oss-cn-shanghai.aliyuncs.com +