From cd9c3c3f4f7a55b8d52a36ff0559931610aa43ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 3 Nov 2022 03:13:27 +0000 Subject: [PATCH] =?UTF-8?q?!243=20=E5=90=88=E5=B9=B6=20oss=20=E7=A7=81?= =?UTF-8?q?=E6=9C=89=E5=BA=93=E5=8A=9F=E8=83=BD=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E6=94=AF=E6=8C=81=20oss=20=E7=A7=81=E6=9C=89?= =?UTF-8?q?=E5=BA=93=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysOssController.java | 22 +- .../system/SysProfileController.java | 3 +- .../java/com/ruoyi/oss/core/OssClient.java | 33 ++- .../com/ruoyi/oss/enumd/AccessPolicyType.java | 55 ++++ .../ruoyi/oss/properties/OssProperties.java | 5 + .../com/ruoyi/system/domain/SysOssConfig.java | 4 + .../system/domain/bo/SysOssConfigBo.java | 6 + .../system/domain/vo/SysOssConfigVo.java | 5 + .../ruoyi/system/service/ISysOssService.java | 6 +- .../service/impl/SysOssServiceImpl.java | 54 +++- ruoyi-ui/src/views/system/oss/config.vue | 24 +- ruoyi-ui/src/views/system/role/selectUser.vue | 276 +++++++++--------- script/sql/ry_vue_4.X.sql | 12 +- 13 files changed, 332 insertions(+), 173 deletions(-) create mode 100644 ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java index 9b9b4d8cc..606895a74 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java @@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.oss.core.OssClient; +import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; import com.ruoyi.system.domain.vo.SysOssVo; @@ -80,7 +82,7 @@ public class SysOssController extends BaseController { if (ObjectUtil.isNull(file)) { throw new ServiceException("上传文件不能为空"); } - SysOss oss = iSysOssService.upload(file); + SysOssVo oss = iSysOssService.upload(file); Map map = new HashMap<>(2); map.put("url", oss.getUrl()); map.put("fileName", oss.getOriginalName()); @@ -96,23 +98,7 @@ public class SysOssController extends BaseController { @SaCheckPermission("system:oss:download") @GetMapping("/download/{ossId}") public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException { - SysOssVo sysOss = iSysOssService.getById(ossId); - if (ObjectUtil.isNull(sysOss)) { - throw new ServiceException("文件数据不存在!"); - } - FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); - long data; - try { - data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false); - } catch (HttpException e) { - if (e.getMessage().contains("403")) { - throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!"); - } else { - throw new ServiceException(e.getMessage()); - } - } - response.setContentLength(Convert.toInt(data)); + iSysOssService.download(ossId,response); } /** diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java index 5c331681e..77a8767de 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -12,6 +12,7 @@ import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.MimeTypeUtils; import com.ruoyi.system.domain.SysOss; +import com.ruoyi.system.domain.vo.SysOssVo; import com.ruoyi.system.service.ISysOssService; import com.ruoyi.system.service.ISysUserService; import lombok.RequiredArgsConstructor; @@ -115,7 +116,7 @@ public class SysProfileController extends BaseController { if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) { return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式"); } - SysOss oss = iSysOssService.upload(avatarfile); + SysOssVo oss = iSysOssService.upload(avatarfile); String avatar = oss.getUrl(); if (userService.updateUserAvatar(getUsername(), avatar)) { ajax.put("imgUrl", avatar); diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java index 15833d3cd..93716c10a 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java @@ -2,6 +2,7 @@ package com.ruoyi.oss.core; import cn.hutool.core.util.IdUtil; import com.amazonaws.ClientConfiguration; +import com.amazonaws.HttpMethod; import com.amazonaws.Protocol; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSCredentialsProvider; @@ -16,12 +17,15 @@ import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.entity.UploadResult; +import com.ruoyi.oss.enumd.AccessPolicyType; import com.ruoyi.oss.enumd.PolicyType; import com.ruoyi.oss.exception.OssException; import com.ruoyi.oss.properties.OssProperties; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.net.URL; +import java.util.Date; /** * S3 存储协议 所有兼容S3协议的云厂商均支持 @@ -57,7 +61,7 @@ public class OssClient { .withClientConfiguration(clientConfig) .withCredentials(credentialsProvider) .disableChunkedEncoding(); - if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)){ + if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) { // minio 使用https限制使用域名访问 需要此配置 站点填域名 build.enablePathStyleAccess(); } @@ -79,9 +83,10 @@ public class OssClient { return; } CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); - createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead); + AccessPolicyType accessPolicy = getAccessPolicy(); + createBucketRequest.setCannedAcl(accessPolicy.getAcl()); client.createBucket(createBucketRequest); - client.setBucketPolicy(bucketName, getPolicy(bucketName, PolicyType.READ)); + client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType())); } catch (Exception e) { throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]"); } @@ -98,7 +103,7 @@ public class OssClient { metadata.setContentLength(inputStream.available()); PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata); // 设置上传对象的 Acl 为公共读 - putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead); + putObjectRequest.setCannedAcl(getAccessPolicy().getAcl()); client.putObject(putObjectRequest); } catch (Exception e) { throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); @@ -138,7 +143,7 @@ public class OssClient { String endpoint = properties.getEndpoint(); String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://"; // 云服务商直接返回 - if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)){ + if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) { if (StringUtils.isNotBlank(domain)) { return header + domain; } @@ -167,6 +172,24 @@ public class OssClient { return configKey; } + public String getPrivateUrl(String objectKey, Integer second) { + GeneratePresignedUrlRequest generatePresignedUrlRequest = + new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey) + .withMethod(HttpMethod.GET) + .withExpiration(new Date(System.currentTimeMillis() + 1000L * second)); + URL url = client.generatePresignedUrl(generatePresignedUrlRequest); + return url.toString(); + } + + /** + * 获取当前桶权限类型 + * + * @return 当前桶权限类型code + */ + public AccessPolicyType getAccessPolicy() { + return AccessPolicyType.getByType(properties.getAccessPolicy()); + } + private static String getPolicy(String bucketName, PolicyType policyType) { StringBuilder builder = new StringBuilder(); builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n"); diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java new file mode 100644 index 000000000..1cae67094 --- /dev/null +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java @@ -0,0 +1,55 @@ +package com.ruoyi.oss.enumd; + +import com.amazonaws.services.s3.model.CannedAccessControlList; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 桶访问策略配置 + * + * @author 陈賝 + */ +@Getter +@AllArgsConstructor +public enum AccessPolicyType { + + /** + * private + */ + PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE), + + /** + * public + */ + PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ), + + /** + * custom + */ + CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ); + + /** + * 桶 权限类型 + */ + private final String type; + + /** + * 文件对象 权限类型 + */ + private final CannedAccessControlList acl; + + /** + * 桶策略类型 + */ + private final PolicyType policyType; + + public static AccessPolicyType getByType(String type) { + for (AccessPolicyType value : values()) { + if (value.getType().equals(type)) { + return value; + } + } + throw new RuntimeException("'type' not found By " + type); + } + +} diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java index a01777901..781a17005 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java @@ -50,4 +50,9 @@ public class OssProperties { */ private String isHttps; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java index 577f17fb8..7f2b05f6a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java @@ -82,4 +82,8 @@ public class SysOssConfig extends BaseEntity { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java index e9f481d5e..af289376c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java @@ -98,4 +98,10 @@ public class SysOssConfigBo extends BaseEntity { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + @NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class}) + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java index f8b31d6b5..616e4e82d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java @@ -82,4 +82,9 @@ public class SysOssConfigVo { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java index f02ea3d98..6472cebcb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java @@ -7,6 +7,8 @@ import com.ruoyi.system.domain.bo.SysOssBo; import com.ruoyi.system.domain.vo.SysOssVo; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.Collection; import java.util.List; @@ -23,7 +25,9 @@ public interface ISysOssService { SysOssVo getById(Long ossId); - SysOss upload(MultipartFile file); + SysOssVo upload(MultipartFile file); + + void download(Long ossId, HttpServletResponse response) throws IOException; Boolean deleteWithValidByIds(Collection ids, Boolean isValid); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java index 6c63821f1..f3bb1365b 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java @@ -1,6 +1,9 @@ package com.ruoyi.system.service.impl; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpException; +import cn.hutool.http.HttpUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -8,10 +11,13 @@ import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.BeanCopyUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.oss.core.OssClient; import com.ruoyi.oss.entity.UploadResult; +import com.ruoyi.oss.enumd.AccessPolicyType; import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; @@ -20,14 +26,17 @@ import com.ruoyi.system.mapper.SysOssMapper; import com.ruoyi.system.service.ISysOssService; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 文件上传 服务层实现 @@ -44,6 +53,8 @@ public class SysOssServiceImpl implements ISysOssService { public TableDataInfo queryPageList(SysOssBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + List filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList()); + result.setRecords(filterResult); return TableDataInfo.build(result); } @@ -53,7 +64,7 @@ public class SysOssServiceImpl implements ISysOssService { for (Long id : ossIds) { SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); if (ObjectUtil.isNotNull(vo)) { - list.add(vo); + list.add(this.matchingUrl(vo)); } } return list; @@ -80,7 +91,28 @@ public class SysOssServiceImpl implements ISysOssService { } @Override - public SysOss upload(MultipartFile file) { + public void download(Long ossId, HttpServletResponse response) throws IOException { + SysOssVo sysOss = this.matchingUrl(SpringUtils.getAopProxy(this).getById(ossId)); + if (ObjectUtil.isNull(sysOss)) { + throw new ServiceException("文件数据不存在!"); + } + FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); + long data; + try { + data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false); + } catch (HttpException e) { + if (e.getMessage().contains("403")) { + throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!"); + } else { + throw new ServiceException(e.getMessage()); + } + } + response.setContentLength(Convert.toInt(data)); + } + + @Override + public SysOssVo upload(MultipartFile file) { String originalfileName = file.getOriginalFilename(); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); OssClient storage = OssFactory.instance(); @@ -98,7 +130,9 @@ public class SysOssServiceImpl implements ISysOssService { oss.setOriginalName(originalfileName); oss.setService(storage.getConfigKey()); baseMapper.insert(oss); - return oss; + SysOssVo sysOssVo = new SysOssVo(); + BeanCopyUtils.copy(oss, sysOssVo); + return this.matchingUrl(sysOssVo); } @Override @@ -114,4 +148,18 @@ public class SysOssServiceImpl implements ISysOssService { return baseMapper.deleteBatchIds(ids) > 0; } + /** + * 匹配Url + * + * @param oss OSS对象 + * @return oss 匹配Url的OSS对象 + */ + private SysOssVo matchingUrl(SysOssVo oss) { + OssClient storage = OssFactory.instance(oss.getService()); + // 仅修改桶类型为 private 的URL,临时URL时长为120s + if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { + oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120)); + } + return oss; + } } diff --git a/ruoyi-ui/src/views/system/oss/config.vue b/ruoyi-ui/src/views/system/oss/config.vue index 54ad98cb1..51f991351 100644 --- a/ruoyi-ui/src/views/system/oss/config.vue +++ b/ruoyi-ui/src/views/system/oss/config.vue @@ -80,6 +80,7 @@ +