From 9fbd156fa0eb3091dd033c3eebf5fbc53c6ab6de Mon Sep 17 00:00:00 2001
From: xin <1099200748@qq.com>
Date: Tue, 03 Jun 2025 02:08:22 +0800
Subject: [PATCH] 桶
---
oying-system/src/main/resources/config/application-dev.yml | 6
oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java | 133 ++++++++++++++
oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java | 22 ++
oying-tools/src/main/java/com/oying/utils/ObsProperties.java | 21 ++
oying-tools/src/main/java/com/oying/domain/BucketStorage.java | 49 +++++
oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java | 25 ++
oying-tools/src/main/java/com/oying/service/BucketStorageService.java | 57 ++++++
oying-tools/src/main/java/com/oying/utils/ObsUtils.java | 127 ++++++++++++++
oying-system/src/main/resources/config/application-prod.yml | 6
oying-tools/src/main/java/com/oying/rest/BucketStorageController.java | 78 ++++++++
pom.xml | 6
11 files changed, 530 insertions(+), 0 deletions(-)
diff --git a/oying-system/src/main/resources/config/application-dev.yml b/oying-system/src/main/resources/config/application-dev.yml
index 3ea16c0..eea81b5 100644
--- a/oying-system/src/main/resources/config/application-dev.yml
+++ b/oying-system/src/main/resources/config/application-dev.yml
@@ -170,3 +170,9 @@
notify-url: https://localhost/oying/api/swiftPass/alipayCallback
# 退款通知地址
refund-url: https://localhost/oying/api/swiftPass/returnNotify
+
+obs:
+ access_key_id: RZ1UIOZDZ58DD4NWPD6Q
+ access_key_secret: QpE58YEFtgoIwUoGNlN5JlNY7t6qVu7vMkix8gAI
+ bucket: oying
+ endpoint: https://obs.cn-southwest-2.myhuaweicloud.com
diff --git a/oying-system/src/main/resources/config/application-prod.yml b/oying-system/src/main/resources/config/application-prod.yml
index cefa2d9..67e895d 100644
--- a/oying-system/src/main/resources/config/application-prod.yml
+++ b/oying-system/src/main/resources/config/application-prod.yml
@@ -180,3 +180,9 @@
notify-url: https://localhost/oying/api/swiftPass/alipayCallback
# 退款通知地址
refund-url: https://localhost/oying/api/swiftPass/returnNotify
+
+obs:
+ access_key_id: RZ1UIOZDZ58DD4NWPD6Q
+ access_key_secret: QpE58YEFtgoIwUoGNlN5JlNY7t6qVu7vMkix8gAI
+ bucket: oying
+ endpoint: https://obs.cn-southwest-2.myhuaweicloud.com
diff --git a/oying-tools/src/main/java/com/oying/domain/BucketStorage.java b/oying-tools/src/main/java/com/oying/domain/BucketStorage.java
new file mode 100644
index 0000000..9baedd1
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/domain/BucketStorage.java
@@ -0,0 +1,49 @@
+package com.oying.domain;
+
+import com.oying.base.BaseEntity;
+import cn.hutool.core.bean.BeanUtil;
+import io.swagger.annotations.ApiModelProperty;
+import cn.hutool.core.bean.copier.CopyOptions;
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+* @description /
+* @author lixin
+* @date 2025-06-03
+**/
+@Getter
+@Setter
+@TableName("tool_bucket_storage")
+public class BucketStorage extends BaseEntity implements Serializable {
+
+ @TableId(value = "bucket_id", type = IdType.AUTO)
+ @ApiModelProperty(value = "主键")
+ private Long bucketId;
+
+ @ApiModelProperty(value = "文件真实的名称")
+ private String realName;
+
+ @ApiModelProperty(value = "文件名")
+ private String name;
+
+ @ApiModelProperty(value = "后缀")
+ private String suffix;
+
+ @ApiModelProperty(value = "路径")
+ private String path;
+
+ @ApiModelProperty(value = "类型")
+ private String type;
+
+ @ApiModelProperty(value = "大小")
+ private String size;
+
+ public void copy(BucketStorage source){
+ BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
+ }
+}
diff --git a/oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java b/oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java
new file mode 100644
index 0000000..32811d9
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java
@@ -0,0 +1,25 @@
+package com.oying.domain.dto;
+
+import lombok.Data;
+import java.sql.Timestamp;
+import java.util.List;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+* @author lixin
+* @date 2025-06-03
+**/
+@Data
+public class BucketStorageQueryCriteria{
+
+ @ApiModelProperty(value = "页码", example = "1")
+ private Integer page = 1;
+
+ @ApiModelProperty(value = "每页数据量", example = "10")
+ private Integer size = 10;
+
+ @ApiModelProperty(value = "模糊查询")
+ private String blurry;
+
+ private List<Timestamp> createTime;
+}
diff --git a/oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java b/oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java
new file mode 100644
index 0000000..395a18c
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java
@@ -0,0 +1,22 @@
+package com.oying.mapper;
+
+import com.oying.domain.BucketStorage;
+import com.oying.domain.dto.BucketStorageQueryCriteria;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+/**
+* @author lixin
+* @date 2025-06-03
+**/
+@Mapper
+public interface BucketStorageMapper extends BaseMapper<BucketStorage> {
+
+ IPage<BucketStorage> findAll(@Param("criteria") BucketStorageQueryCriteria criteria, Page<Object> page);
+
+ List<BucketStorage> findAll(@Param("criteria") BucketStorageQueryCriteria criteria);
+}
diff --git a/oying-tools/src/main/java/com/oying/rest/BucketStorageController.java b/oying-tools/src/main/java/com/oying/rest/BucketStorageController.java
new file mode 100644
index 0000000..c0873e0
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/rest/BucketStorageController.java
@@ -0,0 +1,78 @@
+package com.oying.rest;
+
+import com.oying.annotation.Log;
+import com.oying.domain.BucketStorage;
+import com.oying.exception.BadRequestException;
+import com.oying.service.BucketStorageService;
+import com.oying.domain.dto.BucketStorageQueryCriteria;
+import com.oying.utils.FileUtil;
+import lombok.RequiredArgsConstructor;
+import java.util.List;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import io.swagger.annotations.*;
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oying.utils.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+* @author lixin
+* @date 2025-06-03
+**/
+@RestController
+@RequiredArgsConstructor
+@Api(tags = "存储桶")
+@RequestMapping("/api/bucketStorage")
+public class BucketStorageController {
+
+ private final BucketStorageService bucketStorageService;
+
+ @ApiOperation("导出数据")
+ @GetMapping(value = "/download")
+ @PreAuthorize("@el.check('bucketStorage:list')")
+ public void exportBucketStorage(HttpServletResponse response, BucketStorageQueryCriteria criteria) throws IOException {
+ bucketStorageService.download(bucketStorageService.queryAll(criteria), response);
+ }
+
+ @GetMapping
+ @ApiOperation("查询存储桶")
+ @PreAuthorize("@el.check('bucketStorage:list')")
+ public ResponseEntity<PageResult<BucketStorage>> queryBucketStorage(BucketStorageQueryCriteria criteria){
+ Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize());
+ return new ResponseEntity<>(bucketStorageService.queryAll(criteria,page),HttpStatus.OK);
+ }
+
+ @PostMapping
+ @Log("上传存储桶文件")
+ @ApiOperation("上传存储桶文件")
+ @PreAuthorize("@el.check('bucketStorage:add')")
+ public ResponseEntity<Object> create(@RequestParam String name, @RequestParam("file") MultipartFile file) {
+ return new ResponseEntity<>(bucketStorageService.create(name, file), HttpStatus.CREATED);
+ }
+
+ @PostMapping("/pictures")
+ @ApiOperation("上传图片")
+ public ResponseEntity<Object> upload(@RequestParam MultipartFile file) {
+ // 判断文件是否为图片
+ String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
+ FileUtil.checkSize(5, file.getSize());
+ if (!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))) {
+ throw new BadRequestException("只能上传图片");
+ }
+ BucketStorage bucketStorage = bucketStorageService.create(null, file);
+ return new ResponseEntity<>(bucketStorage, HttpStatus.OK);
+ }
+
+ @DeleteMapping
+ @Log("删除存储桶")
+ @ApiOperation("删除存储桶")
+ @PreAuthorize("@el.check('bucketStorage:del')")
+ public ResponseEntity<Object> deleteBucketStorage(@ApiParam(value = "传ID数组[]") @RequestBody List<Long> ids) {
+ bucketStorageService.deleteAll(ids);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/oying-tools/src/main/java/com/oying/service/BucketStorageService.java b/oying-tools/src/main/java/com/oying/service/BucketStorageService.java
new file mode 100644
index 0000000..3b6dd6b
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/service/BucketStorageService.java
@@ -0,0 +1,57 @@
+package com.oying.service;
+
+import com.oying.domain.BucketStorage;
+import com.oying.domain.dto.BucketStorageQueryCriteria;
+
+import java.io.File;
+import java.util.List;
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.oying.utils.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+* @description 服务接口
+* @author lixin
+* @date 2025-06-03
+**/
+public interface BucketStorageService extends IService<BucketStorage> {
+
+ /**
+ * 查询数据分页
+ * @param criteria 条件
+ * @param page 分页参数
+ * @return PageResult
+ */
+ PageResult<BucketStorage> queryAll(BucketStorageQueryCriteria criteria, Page<Object> page);
+
+ /**
+ * 查询所有数据不分页
+ * @param criteria 条件参数
+ * @return List<BucketStorageDto>
+ */
+ List<BucketStorage> queryAll(BucketStorageQueryCriteria criteria);
+
+ /**
+ * 创建
+ */
+ BucketStorage create(String name, MultipartFile file);
+
+ BucketStorage createFile(String name, File file);
+
+ /**
+ * 多选删除
+ * @param ids /
+ */
+ void deleteAll(List<Long> ids);
+
+ /**
+ * 导出数据
+ * @param all 待导出的数据
+ * @param response /
+ * @throws IOException /
+ */
+ void download(List<BucketStorage> all, HttpServletResponse response) throws IOException;
+}
diff --git a/oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java b/oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java
new file mode 100644
index 0000000..6d60979
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java
@@ -0,0 +1,133 @@
+package com.oying.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.obs.services.internal.ObsProperties;
+import com.obs.services.model.AccessControlList;
+import com.obs.services.model.PutObjectResult;
+import com.oying.domain.BucketStorage;
+import com.oying.utils.FileUtil;
+import lombok.RequiredArgsConstructor;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.oying.service.BucketStorageService;
+import com.oying.domain.dto.BucketStorageQueryCriteria;
+import com.oying.mapper.BucketStorageMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.oying.utils.PageUtil;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import com.oying.utils.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+* @description 服务实现
+* @author lixin
+* @date 2025-06-03
+**/
+@Service
+@RequiredArgsConstructor
+public class BucketStorageServiceImpl extends ServiceImpl<BucketStorageMapper, BucketStorage> implements BucketStorageService {
+
+ private final BucketStorageMapper bucketStorageMapper;
+ private final ObsProperties
+
+ @Override
+ public PageResult<BucketStorage> queryAll(BucketStorageQueryCriteria criteria, Page<Object> page){
+ return PageUtil.toPage(bucketStorageMapper.findAll(criteria, page));
+ }
+
+ @Override
+ public List<BucketStorage> queryAll(BucketStorageQueryCriteria criteria){
+ return bucketStorageMapper.findAll(criteria);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public BucketStorage createFile(String name, File file) {
+ ObsConfig config = obsConfigService.findById(1L);
+ FileUtil.checkSize(properties.getMaxSize(), file.length());
+ String suffix = FileUtil.getExtensionName(file.getName());
+ String type = FileUtil.getFileType(suffix);
+ String reaName = System.currentTimeMillis() + "." + suffix;
+ String objectKey = type + "/" + reaName;
+ PutObjectResult result = ObsUtils.putObject(config, file, objectKey, AccessControlList.REST_CANNED_PUBLIC_READ);
+ if (ObjectUtil.isNull(result)) {
+ throw new BadRequestException("上传失败");
+ }
+ name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(reaName) : name;
+ BucketStorage bucketStorage = new BucketStorage(
+ reaName,
+ name,
+ suffix,
+ objectKey,
+ type,
+ FileUtil.getSize(file.length())
+ );
+ return bucketStorageRepository.save(bucketStorage);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public BucketStorage create(String name, MultipartFile file) {
+ FileUtil.checkSize(properties.getMaxSize(), file.getSize());
+ String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
+ String type = FileUtil.getFileType(suffix);
+ String reaName = System.currentTimeMillis() + "." + suffix;
+ String objectKey = type + "/" + reaName;
+ PutObjectResult result = ObsUtils.putObject(config, FileUtil.toFile(file), objectKey,AccessControlList.REST_CANNED_PUBLIC_READ);
+ if (ObjectUtil.isNull(result)) {
+ throw new BadRequestException("上传失败");
+ }
+ name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(reaName) : name;
+ BucketStorage bucketStorage = new BucketStorage(
+ reaName,
+ name,
+ suffix,
+ objectKey,
+ type,
+ FileUtil.getSize(file.getSize())
+ );
+ return bucketStorageRepository.save(bucketStorage);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void update(BucketStorage resources) {
+ BucketStorage bucketStorage = getById(resources.getBucketId());
+ bucketStorage.copy(resources);
+ bucketStorageMapper.updateById(bucketStorage);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteAll(List<Long> ids) {
+ bucketStorageMapper.deleteBatchIds(ids);
+ }
+
+ @Override
+ public void download(List<BucketStorage> all, HttpServletResponse response) throws IOException {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (BucketStorage bucketStorage : all) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("文件真实的名称", bucketStorage.getRealName());
+ map.put("文件名", bucketStorage.getName());
+ map.put("后缀", bucketStorage.getSuffix());
+ map.put("路径", bucketStorage.getPath());
+ map.put("类型", bucketStorage.getType());
+ map.put("大小", bucketStorage.getSize());
+ map.put("创建人", bucketStorage.getCreateBy());
+ map.put("创建时间", bucketStorage.getCreateTime());
+ map.put("修改者", bucketStorage.getUpdateBy());
+ map.put("修改时间", bucketStorage.getUpdateTime());
+ list.add(map);
+ }
+ FileUtil.downloadExcel(list, response);
+ }
+}
diff --git a/oying-tools/src/main/java/com/oying/utils/ObsProperties.java b/oying-tools/src/main/java/com/oying/utils/ObsProperties.java
new file mode 100644
index 0000000..c6e0724
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/utils/ObsProperties.java
@@ -0,0 +1,21 @@
+package com.oying.utils;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author xin
+ * @description
+ * @date 2025/6/3 01:54
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "obs")
+public class ObsProperties {
+
+ private String accessKeyId;
+ private String accessKeySecret;
+ private String bucket;
+ private String endpoint;
+}
diff --git a/oying-tools/src/main/java/com/oying/utils/ObsUtils.java b/oying-tools/src/main/java/com/oying/utils/ObsUtils.java
new file mode 100644
index 0000000..23c45fe
--- /dev/null
+++ b/oying-tools/src/main/java/com/oying/utils/ObsUtils.java
@@ -0,0 +1,127 @@
+package com.oying.utils;
+
+import com.obs.services.ObsClient;
+import com.obs.services.model.AccessControlList;
+import com.obs.services.model.ObsObject;
+import com.obs.services.model.PutObjectRequest;
+import com.obs.services.model.PutObjectResult;
+import com.oying.exception.BadRequestException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+
+public class ObsUtils {
+
+
+
+ /**
+ * 创建ObsClient实例
+ *
+ * @param properties obs配置
+ * @return ObsClient实例
+ */
+ public static ObsClient getObsClient(ObsProperties properties) {
+ // 创建ObsClient实例
+ return new ObsClient(properties.getAccessKeyId(), properties.getAccessKeySecret(), properties.getEndpoint());
+ }
+
+ /**
+ * 上传对象权限
+ *
+ * @param properties obs配置
+ * @param file 文件
+ * @param objectKey 对象名
+ * @param acl 对象权限
+ * @return PutObjectResult
+ */
+ public static PutObjectResult putObject(ObsProperties properties, File file, String objectKey, AccessControlList acl) {
+ try {
+ // 创建ObsClient实例
+ ObsClient obsClient = getObsClient(properties);
+ PutObjectRequest request = new PutObjectRequest();
+ request.setBucketName(properties.getBucket());
+ request.setObjectKey(objectKey);
+ request.setFile(file);
+ // 对象权限
+ request.setAcl(acl);
+ // 为待上传的本地文件路径,需要指定到具体的文件名
+ return obsClient.putObject(request);
+ } catch (Exception e) {
+ throw new BadRequestException("上传对象失败" + e.getMessage());
+ } finally {
+ FileUtil.del(file);
+ }
+ }
+
+ /**
+ * 上传对象
+ *
+ * @param properties obs配置
+ * @param file 文件
+ * @param objectKey 对象名
+ * @return PutObjectResult
+ */
+ public static PutObjectResult putObject(ObsProperties properties, File file, String objectKey) {
+ try {
+ // 创建ObsClient实例
+ ObsClient obsClient = getObsClient(properties);
+ // 为待上传的本地文件路径,需要指定到具体的文件名
+ return obsClient.putObject(properties.getBucket(), objectKey, file);
+ } catch (Exception e) {
+ throw new BadRequestException("上传对象失败" + e.getMessage());
+ } finally {
+ FileUtil.del(file);
+ }
+ }
+
+ /**
+ * 下载对象
+ *
+ * @param properties obs配置
+ * @param objectKey 对象名
+ * @param path 保存路径
+ */
+ public static String getObject(ObsProperties properties, String objectKey, String path) {
+ // 创建ObsClient实例
+ ObsClient obsClient = getObsClient(properties);
+ ObsObject obsObject = obsClient.getObject(properties.getBucket(), objectKey);
+ InputStream in = obsObject.getObjectContent();
+ if (in != null) {
+ FileOutputStream out = null;
+ try {
+ // getCanonicalFile 可解析正确各种路径
+ File dest = new File(path).getCanonicalFile();
+ // 检测是否存在目录
+ if (!dest.getParentFile().exists()) {
+ dest.getParentFile().mkdirs();
+ }
+ out = new FileOutputStream(path);
+ byte[] b = new byte[1024];
+ int length;
+ while ((length = in.read(b)) > 0) {
+ out.write(b, 0, length);
+ }
+ } catch (Exception e) {
+ throw new BadRequestException("流输出异常");
+ } finally {
+ CloseUtil.close(in);
+ CloseUtil.close(out);
+ }
+ }
+ return path;
+ }
+
+ /**
+ * 删除对象
+ *
+ * @param properties obs配置
+ * @param objectKey 对象名
+ */
+ public static void deleteObject(ObsProperties properties, String objectKey) {
+ // 创建ObsClient实例
+ ObsClient obsClient = getObsClient(properties);
+ // 删除指定的对象
+ obsClient.deleteObject(properties.getBucket(), objectKey);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 489ecc4..1264ba2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -236,6 +236,12 @@
<artifactId>commons-text</artifactId>
<version>1.13.0</version>
</dependency>
+ <!-- 华为云对象存储服务 OBS-->
+ <dependency>
+ <groupId>com.huaweicloud</groupId>
+ <artifactId>esdk-obs-java-bundle</artifactId>
+ <version>3.22.12</version>
+ </dependency>
</dependencies>
<build>
--
Gitblit v1.9.3