xin
2025-06-03 9fbd156fa0eb3091dd033c3eebf5fbc53c6ab6de

8 files added
3 files modified
530 ■■■■■ changed files
oying-system/src/main/resources/config/application-dev.yml 6 ●●●●● patch | view | raw | blame | history
oying-system/src/main/resources/config/application-prod.yml 6 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/domain/BucketStorage.java 49 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java 25 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java 22 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/rest/BucketStorageController.java 78 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/service/BucketStorageService.java 57 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java 133 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/utils/ObsProperties.java 21 ●●●●● patch | view | raw | blame | history
oying-tools/src/main/java/com/oying/utils/ObsUtils.java 127 ●●●●● patch | view | raw | blame | history
pom.xml 6 ●●●●● patch | view | raw | blame | history
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
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
oying-tools/src/main/java/com/oying/domain/BucketStorage.java
New file
@@ -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));
    }
}
oying-tools/src/main/java/com/oying/domain/dto/BucketStorageQueryCriteria.java
New file
@@ -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;
}
oying-tools/src/main/java/com/oying/mapper/BucketStorageMapper.java
New file
@@ -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);
}
oying-tools/src/main/java/com/oying/rest/BucketStorageController.java
New file
@@ -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);
    }
}
oying-tools/src/main/java/com/oying/service/BucketStorageService.java
New file
@@ -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;
}
oying-tools/src/main/java/com/oying/service/impl/BucketStorageServiceImpl.java
New file
@@ -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);
    }
}
oying-tools/src/main/java/com/oying/utils/ObsProperties.java
New file
@@ -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;
}
oying-tools/src/main/java/com/oying/utils/ObsUtils.java
New file
@@ -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);
    }
}
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>