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