去除多余的模块和提那家tcp模块

This commit is contained in:
haozq 2024-08-09 14:02:39 +08:00
parent 1c3f87ad7a
commit 7975796964
37 changed files with 91 additions and 2092 deletions

View File

@ -134,7 +134,7 @@ public class SidebandController extends BaseController {
* @return
*/
@PostMapping("delDevice")
@SysLog(title = "边带管理", businessType = OperaType.QUERY, logType = 0, module = "施工管控->边带管理", details = "解除绑定")
@SysLog(title = "边带管理", businessType = OperaType.QUERY, module = "施工管控->边带管理", details = "解除绑定")
public AjaxResult delDevice(@RequestBody SidebandDeviceVo vo) {
return sidebandservice.delDevice(vo);
}
@ -145,7 +145,7 @@ public class SidebandController extends BaseController {
* @return
*/
@PostMapping("bindDevice")
@SysLog(title = "边带管理", businessType = OperaType.QUERY, logType = 0, module = "施工管控->边带管理", details = "绑定")
@SysLog(title = "边带管理", businessType = OperaType.QUERY, module = "施工管控->边带管理", details = "绑定")
public AjaxResult bindDevice(@RequestBody BindDeviceVo vo) {
int sidebandId = vo.getSidebandId();
List<Map<String,Object>> list= vo.getDeviceIds();

View File

@ -1,25 +0,0 @@
package com.bonus.mongodb;
import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class BonusMongodbApplication {
public static void main(String[] args)
{
SpringApplication.run(BonusMongodbApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ MongoDB存储服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -1,63 +0,0 @@
package com.bonus.mongodb.config;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.URLEncoder;
/**
* @author coisini
* @version 1.0
* @Description MongoDB配置类
* @date Apr 17, 2022
*/
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb")
@Data
public class MongoConfig {
/**
* 数据库配置信息
*/
private String database;
private String host;
private Integer port;
private String username;
private String password;
// 移除静态修饰符避免单例模式
private MongoClient mongoClient;
// 使用@Bean注解并在方法内部进行异常处理
@Bean
public MongoClient getMongoClient() {
if (mongoClient == null) {
try {
mongoClient = MongoClients.create(String.format("mongodb://%s:%s@%s:%d/%s", URLEncoder.encode(username, "UTF-8"),URLEncoder.encode(password, "UTF-8"), host, port, database));
} catch (Exception e) {
// 在实际应用中应该有更详细的异常处理策略例如记录日志并抛出自定义异常
throw new RuntimeException("Failed to create MongoClient", e);
}
}
return mongoClient;
}
// 直接返回MongoDatabase实例依赖注入会处理实例的获取
public MongoDatabase getMongoDatabase() {
return getMongoClient().getDatabase(database);
}
// 创建GridFSBucket的@Bean方法依赖注入MongoDatabase
@Bean
public GridFSBucket getGridFsBucket() {
return GridFSBuckets.create(getMongoDatabase());
}
}

View File

@ -1,75 +0,0 @@
package com.bonus.mongodb.controller;
import com.bonus.common.core.domain.R;
import com.bonus.mongodb.damain.FileExportVo;
import com.bonus.mongodb.service.MongodbService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/mongodb/")
@Slf4j
public class MongodbController {
@Resource
private MongodbService mongodbService;
@ApiOperation(value = "单文件上传")
@PostMapping("uploadFile")
public R<FileExportVo> uploadFile(MultipartFile file) {
try {
FileExportVo fileExportVo = mongodbService.uploadFile(file);
return R.ok(fileExportVo);
} catch (Exception e) {
log.error("单文件上传", e);
return R.fail();
}
}
@ApiOperation(value = "多文件上传")
@PostMapping("uploadFiles")
public R<List<FileExportVo>> uploadFiles(MultipartFile[] files) {
try {
List<MultipartFile> multipartFiles = Arrays.asList(files);
List<FileExportVo> list = mongodbService.uploadFiles(multipartFiles);
return R.ok(list);
} catch (Exception e) {
log.error("多文件上传", e);
return R.fail();
}
}
@ApiOperation(value = "文件删除")
@PostMapping("delFile")
public R<T> delFile(String fileId) {
try {
mongodbService.removeFile(fileId);
return R.ok();
} catch (Exception e) {
log.error("文件删除", e);
return R.fail();
}
}
@ApiOperation(value = "获取文件base64")
@PostMapping("getFileBase64")
public R<byte[]> getFileBase64(String fileId) {
try {
FileExportVo fileExportVo = mongodbService.downloadFile(fileId);
return R.ok(fileExportVo.getData());
} catch (Exception e) {
log.error("获取文件base64", e);
return R.fail();
}
}
}

View File

@ -1,44 +0,0 @@
package com.bonus.mongodb.damain;
import java.io.Serializable;
import java.util.Objects;
import cn.hutool.core.bean.BeanUtil;
import lombok.Data;
@Data
public class FileExportVo implements Serializable {
private String file;
private String fileId;
private String fileName;
private String contentType;
private String suffix;
private long fileSize;
private String sourceId;
private String id;
private String fileType;
/**
* 资源类型
*/
private String sourceType;
private String updaetTime;
private byte[] data;
public FileExportVo(MongoFile mongoFile) {
BeanUtil.copyProperties(mongoFile, this);
if (Objects.nonNull(mongoFile.getContent())) {
this.data = mongoFile.getContent().getData();
}
this.fileId = mongoFile.getId();
}
}

View File

@ -1,63 +0,0 @@
package com.bonus.mongodb.damain;
import lombok.Builder;
import lombok.Data;
import org.bson.types.Binary;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Builder
@Data
@Document(collection = "files")
public class MongoFile {
/**
* 主键
*/
@Id
public String id;
/**
* 文件名称
*/
public String fileName;
/**
* 文件大小
*/
public long fileSize;
/**
* 上传时间
*/
public String uploadDate;
/**
* MD5值
*/
public String md5;
/**
* 文件内容
*/
private Binary content;
/**
* 文件类型
*/
public String contentType;
/**
* 文件后缀名
*/
public String suffix;
/**
* 文件描述
*/
public String description;
/**
* 大文件管理GridFS的ID
*/
private String gridFsId;
}

View File

@ -1,8 +0,0 @@
package com.bonus.mongodb.repository;
import com.bonus.mongodb.damain.MongoFile;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface MongoFileRepository extends MongoRepository<MongoFile, String> {
}

View File

@ -1,43 +0,0 @@
package com.bonus.mongodb.service;
import com.bonus.mongodb.damain.FileExportVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface MongodbService {
/**
* 文件上传
*
* @param file
* @return FileExportVo
* @throws Exception
* @description
* @date 2024/3/11 15:44
*/
FileExportVo uploadFile(MultipartFile file) throws Exception;
/**
* 多文件上传
*
* @param files
* @return
*/
List<FileExportVo> uploadFiles(List<MultipartFile> files);
/**
* 文件下载
*
* @param fileId
* @return
*/
FileExportVo downloadFile(String fileId);
/**
* 文件删除
*
* @param fileId
*/
void removeFile(String fileId);
}

View File

@ -1,279 +0,0 @@
package com.bonus.mongodb.service.impl;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.mongodb.damain.FileExportVo;
import com.bonus.mongodb.damain.MongoFile;
import com.bonus.mongodb.repository.MongoFileRepository;
import com.bonus.mongodb.service.MongodbService;
import com.bonus.mongodb.utils.Md5Util;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import lombok.RequiredArgsConstructor;
import org.bson.types.Binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MongodbServiceImpl implements MongodbService {
private static final Logger log = LoggerFactory.getLogger(MongodbServiceImpl.class);
private final MongoFileRepository mongoFileRepository;
private final MongoTemplate mongoTemplate;
private final GridFsTemplate gridFsTemplate;
private final GridFSBucket gridFSBucket;
private static final int MAX_SIZE = 16777216;
private static final String SUFFIX = ".";
/**
* 多文件上传
*
* @param files
* @return
*/
@Override
public List<FileExportVo> uploadFiles(List<MultipartFile> files) {
return files.stream().map(file -> {
try {
return this.uploadFile(file);
} catch (Exception e) {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}
/**
* 文件上传
*
* @param file
* @return
* @throws Exception
*/
@Override
public FileExportVo uploadFile(MultipartFile file) throws Exception {
if (file.getSize() > MAX_SIZE) {
return this.saveGridFsFile(file);
} else {
return this.saveBinaryFile(file);
}
}
/**
* 文件下载
*
* @param fileId
* @return
*/
@Override
public FileExportVo downloadFile(String fileId) {
Optional<MongoFile> option = this.getBinaryFileById(fileId);
if (option.isPresent()) {
MongoFile mongoFile = option.get();
if (Objects.isNull(mongoFile.getContent())) {
option = this.getGridFsFileById(fileId);
}
}
return option.map(FileExportVo::new).orElse(null);
}
/**
* 文件删除
*
* @param fileId
*/
@Override
public void removeFile(String fileId) {
Optional<MongoFile> option = this.getBinaryFileById(fileId);
if (option.isPresent()) {
if (Objects.nonNull(option.get().getGridFsId())) {
this.removeGridFsFile(fileId);
} else {
this.removeBinaryFile(fileId);
}
}
}
/**
* 删除Binary文件
*
* @param fileId
*/
public void removeBinaryFile(String fileId) {
mongoFileRepository.deleteById(fileId);
}
/**
* 删除GridFs文件
*
* @param fileId
*/
public void removeGridFsFile(String fileId) {
// TODO 根据id查询文件
MongoFile mongoFile = mongoTemplate.findById(fileId, MongoFile.class);
if (Objects.nonNull(mongoFile)) {
// TODO 根据文件ID删除fs.files和fs.chunks中的记录
Query deleteFileQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId()));
gridFsTemplate.delete(deleteFileQuery);
// TODO 删除集合mongoFile中的数据
Query deleteQuery = new Query(Criteria.where("id").is(fileId));
mongoTemplate.remove(deleteQuery, MongoFile.class);
}
}
/**
* 保存Binary文件小文件
*
* @param file
* @return
* @throws Exception
*/
public FileExportVo saveBinaryFile(MultipartFile file) throws Exception {
String suffix = getFileSuffix(file);
MongoFile mongoFile = mongoFileRepository.save(
MongoFile.builder()
.fileName(file.getOriginalFilename())
.fileSize(file.getSize())
.content(new Binary(file.getBytes()))
.contentType(file.getContentType())
.uploadDate(DateUtils.getTime())
.suffix(suffix)
.md5(Md5Util.getMd5(file.getInputStream()))
.build()
);
return new FileExportVo(mongoFile);
}
/**
* 保存GridFs文件大文件
*
* @param file
* @return
* @throws Exception
*/
public FileExportVo saveGridFsFile(MultipartFile file) throws Exception {
String suffix = getFileSuffix(file);
String gridFsId = this.storeFileToGridFs(file.getInputStream(), file.getContentType());
MongoFile mongoFile = mongoTemplate.save(
MongoFile.builder()
.fileName(file.getOriginalFilename())
.fileSize(file.getSize())
.contentType(file.getContentType())
.uploadDate(DateUtils.getTime())
.suffix(suffix)
.md5(Md5Util.getMd5(file.getInputStream()))
.gridFsId(gridFsId)
.build()
);
return new FileExportVo(mongoFile);
}
/**
* 上传文件到Mongodb的GridFs中
*
* @param in
* @param contentType
* @return
*/
public String storeFileToGridFs(InputStream in, String contentType) throws IOException {
try {
String gridFsId = IdUtil.simpleUUID();
// TODO 将文件存储进GridFS中
gridFsTemplate.store(in, gridFsId, contentType);
return gridFsId;
}catch (Exception e){
log.error("上传文件到Mongodb的GridFs中失败",e);
}
finally {
in.close();
}
return null;
}
/**
* 获取Binary文件
*
* @param id
* @return
*/
public Optional<MongoFile> getBinaryFileById(String id) {
return mongoFileRepository.findById(id);
}
/**
* 获取Grid文件
*
* @param id
* @return
*/
public Optional<MongoFile> getGridFsFileById(String id) {
MongoFile mongoFile = mongoTemplate.findById(id, MongoFile.class);
if (Objects.nonNull(mongoFile)) {
Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId()));
try {
// TODO 根据id查询文件
GridFSFile fsFile = gridFsTemplate.findOne(gridQuery);
// TODO 打开流下载对象
GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId());
if (in.getGridFSFile().getLength() > 0) {
// TODO 获取流对象
GridFsResource resource = new GridFsResource(fsFile, in);
// TODO 获取数据
mongoFile.setContent(new Binary(IoUtil.readBytes(resource.getInputStream())));
return Optional.of(mongoFile);
} else {
return Optional.empty();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return Optional.empty();
}
/**
* 获取文件后缀
*
* @param file
* @return
*/
private String getFileSuffix(MultipartFile file) {
String suffix = "";
if (Objects.requireNonNull(file.getOriginalFilename()).contains(SUFFIX)) {
suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
}
return suffix;
}
}

View File

@ -1,37 +0,0 @@
package com.bonus.mongodb.utils;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @author 10488
* @version 1.0
* @Description MD5工具类
* @date Apr 8, 2022
*/
public class Md5Util {
/**
* 获取该输入流的MD5值
*/
public static String getMd5(InputStream is) throws NoSuchAlgorithmException, IOException {
StringBuffer md5 = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = is.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
;
byte[] mdbytes = md.digest();
// convert the byte to hex format
for (int i = 0; i < mdbytes.length; i++) {
md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
is.close();
return md5.toString();
}
}

View File

@ -1,29 +0,0 @@
# Tomcat
server:
port: 9206
# Spring
spring:
application:
# 应用名称
name: bonus-mongodb
profiles:
# 环境配置
active: dev
cloud:
nacos:
username: nacos
password: nacos
discovery:
# 服务注册地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
config:
# 配置中心地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bonus</groupId>
<artifactId>bonus-modules</artifactId>
<version>24.6.0</version>
</parent>
<artifactId>bonus-obs</artifactId>
<description>
bonus-modules-obs存储服务
</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- Minio -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<!-- bonus Api System -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-api-system</artifactId>
</dependency>
<!-- bonus Common Swagger -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-swagger</artifactId>
</dependency>
<!-- huaweicloud obs -->
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java-bundle</artifactId>
<version>3.23.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--加密依赖包-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,25 +0,0 @@
package com.bonus.obs;
import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class BonusObsApplication {
public static void main(String[] args)
{
SpringApplication.run(BonusObsApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ obs存储服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -1,50 +0,0 @@
package com.bonus.obs.config;
import com.obs.services.ObsClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "obs")
public class ObsConfig {
private String endpoint;
private String ak;
private String sk;
private String bucket;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getAk() {
return ak;
}
public void setAk(String ak) {
this.ak = ak;
}
public String getSk() {
return sk;
}
public void setSk(String sk) {
this.sk = sk;
}
public String getBucket() {
return bucket;
}
public void setBucket(String bucket) {
this.bucket = bucket;
}
}

View File

@ -1,90 +0,0 @@
package com.bonus.obs.controller;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.utils.file.FileUtils;
import com.bonus.obs.service.ObsService;
import com.obs.services.model.DeleteObjectResult;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("/obs")
public class ObsController {
@Resource
private ObsService service;
/**
* 文件上传
*
* @param param 文件流
* @return 文件信息
*/
@PostMapping("/upload")
public R<PutObjectResult> uploadFile(MultipartFile param) {
return service.uploadFile(param);
}
/**
* 删除文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
@PostMapping("/delete")
public R<DeleteObjectResult> deleteFile(String objectKey) {
return service.deleteFile(objectKey);
}
/**
* 文件下载
*
* @param objectKey obs文件存储地址
*/
@GetMapping("/download")
public void download(HttpServletResponse response, @RequestParam String objectKey) {
R<ObsObject> obsObjectR = service.downloadFile(objectKey);
try {
if (R.isError(obsObjectR)) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
if (obsObjectR.getData() == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
InputStream inputStream = obsObjectR.getData().getObjectContent();
String safeFileName = FileUtils.getFileNameFromPath(objectKey);
String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");
try (OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
} catch (IOException e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
} catch (IllegalArgumentException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
}

View File

@ -1,42 +0,0 @@
package com.bonus.obs.domain;
import lombok.Builder;
import lombok.Data;
/**
* OBSObject Storage Service信息类
* 用于封装与OBS对象相关的元数据信息
*/
@Data
@Builder
public class ObsInfo {
/**
* 对象的名称
* 代表OBS对象的唯一标识
*/
private String name;
/**
* 对象在OBS中的存储路径
* 包含桶bucket名称和对象在桶内的相对路径
*/
private String path;
/**
* 对象的大小
* 以字符串形式表示可能包含单位如字节KBMB等
*/
private String length;
/**
* 对象的文件类型
* 用于标识对象的MIME类型例如text/plainimage/jpeg等
*/
private String fileType;
/**
* 对象所属的桶bucket的名称
* 每个桶在OBS中都是唯一的用于存储对象
*/
private String bucketName;
}

View File

@ -1,40 +0,0 @@
package com.bonus.obs.service;
import com.bonus.common.core.domain.R;
import com.obs.services.model.DeleteObjectResult;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import org.springframework.web.multipart.MultipartFile;
public interface ObsService {
/**
* 文件上传
*
* @param file 文件流
* @return 文件信息
*/
R<PutObjectResult> uploadFile(MultipartFile file);
/**
* 删除文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
public R<DeleteObjectResult> deleteFile(String objectKey);
/**
* 下载文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
public R<ObsObject> downloadFile(String objectKey);
/**
* 文件上传
*
* @param files 文件流
* @return 文件信息
*/
R<PutObjectResult> uploadFiles(MultipartFile[] files);
}

View File

@ -1,68 +0,0 @@
package com.bonus.obs.service.impl;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.utils.file.FileUtils;
import com.bonus.obs.service.ObsService;
import com.bonus.obs.utils.ObsUtils;
import com.obs.services.model.DeleteObjectResult;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
@Service
public class ObsServiceImpl implements ObsService {
@Resource
private ObsUtils obsUtils;
/**
* 文件上传
*
* @param file 文件流
* @return 文件信息
*/
@Override
public R<PutObjectResult> uploadFile(MultipartFile file) {
try {
String objectKey = file.getOriginalFilename();
objectKey = FileUtils.generateObjectName(objectKey);
return obsUtils.uploadFile(objectKey, FileUtils.multipartFileToFile(file));
} catch (Exception e) {
return R.fail(e.getMessage());
}
}
/**
* 删除文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
@Override
public R<DeleteObjectResult> deleteFile(String objectKey) {
return obsUtils.deleteFile(objectKey);
}
/**
* 下载文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
@Override
public R<ObsObject> downloadFile(String objectKey) {
return obsUtils.downloadFile(objectKey);
}
/**
* 文件上传
*
* @param files 文件流
* @return 文件信息
*/
@Override
public R<PutObjectResult> uploadFiles(MultipartFile[] files) {
return null;
}
}

View File

@ -1,85 +0,0 @@
package com.bonus.obs.utils;
import com.bonus.common.core.utils.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileUtils {
/**
* 检查MultipartFile是否有效不为空且大小不超过5GB
*
* @param file MultipartFile对象
* @return 文件有效返回true否则返回false
*/
public static boolean isValidFile(MultipartFile file) {
if (file == null || file.isEmpty()) {
return false;
}
// 文件大小限制为5GB
long maxSizeInBytes = 5L * 1024 * 1024 * 1024;
return file.getSize() <= maxSizeInBytes;
}
/**
* 生成统一路径的objectName
*
* @param fileName 文件名
* @return 生成的objectName
*/
public static String generateObjectName(String fileName) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
String datePath = sdf.format(new Date());
return "uploads/" + datePath + "/" + fileName;
}
public static boolean isValidOssFilePath(String ossFilePath) {
// 根据实际情况添加对ossFilePath的校验逻辑确保其只包含安全的字符
return StringUtils.hasText(ossFilePath) && ossFilePath.matches("^[\\w\\d\\-\\_\\.]+$");
}
public static String sanitizeFileName(String fileName) {
// 避免文件名注入移除或替换不安全的字符
return fileName.replaceAll("[^a-zA-Z0-9\\.\\-_]", "_");
}
/**
* 从文件路径中提取文件名
* @param ossFilePath 文件路径
* @return 文件名
*/
public static String getFileNameFromPath(String ossFilePath) {
Path path = Paths.get(ossFilePath);
return path.getFileName().toString();
}
/**
* MultipartFile File
*
* @param multiFile MultipartFile对象
* @return 转换后的File对象
*/
public static File multipartFileToFile(MultipartFile multiFile) {
try {
String fileName = multiFile.getOriginalFilename();
if (fileName == null) {
return null;
}
String prefix = fileName.substring(0, fileName.lastIndexOf("."));
String suffix = fileName.substring(fileName.lastIndexOf("."));
File file = File.createTempFile(prefix, suffix);
multiFile.transferTo(file);
return file;
} catch (Exception e) {
return null;
}
}
}

View File

@ -1,87 +0,0 @@
package com.bonus.obs.utils;
import com.bonus.common.core.domain.R;
import com.bonus.obs.config.ObsConfig;
import com.obs.services.ObsClient;
import com.obs.services.model.DeleteObjectResult;
import com.obs.services.model.GetObjectRequest;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@Service
public class ObsUtils {
@Resource
private ObsConfig obsConfig;
/**
* obs 客户端
*/
private ObsClient obsClient;
/**
* 初始化信息
* 构建OSS客户端实例
*/
@PostConstruct
public void init() {
obsClient = new ObsClient(obsConfig.getAk(), obsConfig.getSk(), obsConfig.getEndpoint());
}
/**
* 上传文件到OBS
*
* @param file 要上传的文件
* @return 上传结果
*/
public R<PutObjectResult> uploadFile(String objectKey, File file) {
return R.ok(obsClient.putObject(obsConfig.getBucket(), objectKey, file));
}
/**
* 下载文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
public R<ObsObject> downloadFile(String objectKey) {
if (!doesObjectExist(objectKey)) {
return R.fail("文件不存在");
}
return R.ok(obsClient.getObject(new GetObjectRequest(obsConfig.getBucket(), objectKey)));
}
/**
* 删除文件从OBS
*
* @param objectKey 文件在OBS中的键
*/
public R<DeleteObjectResult> deleteFile(String objectKey) {
if (!doesObjectExist(objectKey)) {
return R.fail("文件不存在");
}
return R.ok(obsClient.deleteObject(obsConfig.getBucket(), objectKey));
}
/**
* 判断文件是否存在
*
* @param objectKey 文件在OBS中的键
* @return 如果文件存在则返回true否则返回false
*/
public boolean doesObjectExist(String objectKey) {
try {
return obsClient.doesObjectExist(obsConfig.getBucket(), objectKey);
} catch (Exception e) {
return false;
}
}
}

View File

@ -1,29 +0,0 @@
# Tomcat
server:
port: 9205
# Spring
spring:
application:
# 应用名称
name: bonus-obs
profiles:
# 环境配置
active: dev
cloud:
nacos:
username: nacos
password: nacos
discovery:
# 服务注册地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
config:
# 配置中心地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/bonus-file" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.bonus" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bonus</groupId>
<artifactId>bonus-modules</artifactId>
<version>24.6.0</version>
</parent>
<artifactId>bonus-oss</artifactId>
<description>
bonus-modules-oss存储服务
</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- bonus Common Swagger -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-swagger</artifactId>
</dependency>
<!--阿里云oss 存储-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-core</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--加密依赖包-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,25 +0,0 @@
package com.bonus.oss;
import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class BonusOssApplication {
public static void main(String[] args)
{
SpringApplication.run(BonusOssApplication.class, args);
System.err.println("(♥◠‿◠)ノ゙ oss存储服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -1,40 +0,0 @@
package com.bonus.oss.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 配置OSS对象存储服务的属性类
* 使用@ConfigurationProperties注解将类绑定到配置文件中以oss为前缀的属性上
* 使用@Configuration注解将此类标记为一个配置类它会被Spring Boot自动检测并用于配置上下文
* 使用@Data注解来自动生成getter和setter方法简化了属性访问
*/
@Configuration
@ConfigurationProperties(prefix = "oss")
@Data
public class OSSConfig {
/**
* OSS的访问密钥ID
* 用于身份验证的重要凭证之一
*/
private String accessKeyId;
/**
* OSS的访问密钥秘钥
* 用于身份验证的重要凭证之一应保密
*/
private String accessKeySecret;
/**
* OSS的存储桶名称
* 存储桶是OSS中用于存储对象的容器
*/
private String bucket;
/**
* OSS的Endpoint
* Endpoint指定了与OSS交互时使用的域名或区域
*/
private String endpoint;
}

View File

@ -1,112 +0,0 @@
package com.bonus.oss.controller;
import com.aliyun.oss.model.OSSObject;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.file.FileUtils;
import com.bonus.oss.domain.OssInfo;
import com.bonus.oss.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/oss")
public class OssController {
@Resource
private OssService ossService;
/**
* 文件上传
*
* @param file 文件流
* @return 文件信息
*/
@PostMapping("/uploadFile")
public R<OssInfo> uploadFile(MultipartFile file) {
return ossService.uploadFile(file);
}
/**
* 文件上传
*
* @param files 文件流
* @return 文件信息
*/
@PostMapping("/uploadFiles")
public R<List<OssInfo>> uploadFiles(MultipartFile[] files) {
return ossService.uploadFiles(files);
}
/**
* 文件下载
*
* @param objectKey oss文件存储地址
*/
@GetMapping("/downloadFile")
public void downloadFile(HttpServletResponse response, @RequestParam String objectKey) throws UnsupportedEncodingException {
R<OSSObject> ossObjectR = ossService.downloadFile(objectKey);
if (ossObjectR.getData() == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
OSSObject ossObject = ossObjectR.getData();
String safeFileName = FileUtils.getName(objectKey); // 假设这个方法进行了恰当的文件名清理和验证
if (!StringUtils.hasText(safeFileName)) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");
try (InputStream inputStream = ossObject.getObjectContent();
OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
} catch (IOException e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
} catch (IllegalArgumentException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
} catch (Exception e) {
// 记录异常信息到日志
log.error("文件下载过程中出现未知异常,原因是:", e);
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
/**
* 文件删除
*
* @param objectKey 文件路径
* @return 删除结果
*/
@PostMapping("/deleteFile")
public R<T> deleteFile(@RequestParam String objectKey) {
return ossService.deleteFile(objectKey);
}
}

View File

@ -1,43 +0,0 @@
package com.bonus.oss.domain;
import lombok.Builder;
import lombok.Data;
/**
* OssInfo类用于封装OSSObject Storage Service对象的相关信息
* 通过此类可以方便地管理和访问OSS对象的元数据如名称路径大小等
*/
@Builder
@Data
public class OssInfo {
/**
* 文件或对象的名称
* 用于唯一标识OSS中的一个对象
*/
private String name;
/**
* 文件在OSS中的存储路径
* 该路径不包含Bucket名称仅指对象在Bucket内的相对路径
*/
private String path;
/**
* 文件或对象的大小
* 以字符串形式表示单位可能为字节KBMB等
*/
private String length;
/**
* 文件的类型
* 可以是文件的MIME类型或者根据文件扩展名推测的类型
*/
private String fileType;
/**
* 存储文件的Bucket名称
* Bucket是OSS中用于存储对象的容器每个对象必须属于某个Bucket
*/
private String bucketName;
}

View File

@ -1,43 +0,0 @@
package com.bonus.oss.service;
import com.aliyun.oss.model.OSSObject;
import com.bonus.common.core.domain.R;
import com.bonus.oss.domain.OssInfo;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface OssService {
/**
* 文件上传
*
* @param param 文件流
* @return 文件信息
*/
R<OssInfo> uploadFile(MultipartFile param);
/**
* 文件下载
*
* @param objectKey oss文件存储地址
* @return OSSObject对象
*/
R<OSSObject> downloadFile(String objectKey);
/**
* 文件删除
*
* @param objectKey oss文件存储地址
* @return 操作结果
*/
R<T> deleteFile(String objectKey);
/**
* 多文件上传
*
* @param files 文件流
* @return 文件信息
*/
R<List<OssInfo>> uploadFiles(MultipartFile[] files);
}

View File

@ -1,107 +0,0 @@
package com.bonus.oss.service.impl;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.aliyun.oss.model.OSSObject;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.file.FileUtils;
import com.bonus.oss.domain.OssInfo;
import com.bonus.oss.service.OssService;
import com.bonus.oss.utils.OssUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Service
public class OssServiceImpl implements OssService {
@Resource
private OssUtils ossUtils;
/**
* 文件上传
*
* @param file 文件流
* @return 文件信息
*/
@Override
public R<OssInfo> uploadFile(MultipartFile file) {
if (ObjectUtils.isEmpty(file)) {
return R.fail("File is null.");
}
try {
String originalFilename = Objects.requireNonNull(file.getOriginalFilename(), "文件名不能为空");
String extension = originalFilename.substring(originalFilename.lastIndexOf('.'));
String objectKey = UuidUtils.generateUuid() + extension;
objectKey = FileUtils.generateObjectName(objectKey);
return ossUtils.upload(objectKey, FileUtils.multipartFileToFile(file));
} catch (Exception e) {
return R.fail("File upload failed.");
}
}
/**
* 文件下载
*
* @param objectKey oss文件存储地址
*/
@Override
public R<OSSObject> downloadFile(String objectKey) {
if (ObjectUtils.isEmpty(objectKey)) {
return R.fail("objectKey is null.");
}
return ossUtils.download(objectKey);
}
/**
* 文件删除
*
* @param objectKey oss文件存储地址
*/
@Override
public R<T> deleteFile(String objectKey) {
try {
if (ObjectUtils.isNotEmpty(objectKey)) {
return ossUtils.delete(objectKey);
} else {
return R.fail("objectKey is null.");
}
} catch (Exception e) {
return R.fail("File delete failed.");
}
}
/**
* 多文件上传
*
* @param files 文件流
* @return 文件信息
*/
@Override
public R<List<OssInfo>> uploadFiles(MultipartFile[] files) {
try {
List<OssInfo> ossInfos = new ArrayList<>();
for (MultipartFile multipartFile : files) {
String originalFilename = Objects.requireNonNull(multipartFile.getOriginalFilename(), "文件名不能为空");
String extension = originalFilename.substring(originalFilename.lastIndexOf('.'));
String objectKey = UuidUtils.generateUuid() + extension;
File file = FileUtils.multipartFileToFile(multipartFile);
objectKey = FileUtils.generateObjectName(objectKey);
ossInfos.add(ossUtils.upload(objectKey, file).getData());
}
return R.ok(ossInfos, "文件上传成功");
} catch (Exception e) {
return R.fail("File upload failed.");
}
}
}

View File

@ -1,139 +0,0 @@
package com.bonus.oss.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.text.Convert;
import com.bonus.common.core.utils.file.FileUtils;
import com.bonus.oss.config.OSSConfig;
import com.bonus.oss.domain.OssInfo;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
/**
* OSS存储服务类
*/
@Service
public class OssUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(OssUtils.class);
@Resource
private OSSConfig ossConfig;
/**
* OSS客户端
*/
private OSS ossClient;
/**
* 初始化OSS客户端
*/
@PostConstruct
public void init() {
ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
}
/**
* 上传文件到OSS
*
* @param objectKey 文件在OSS中的键
* @param file 要上传的文件
* @return 包含上传文件信息的结果对象
*/
public R<OssInfo> upload(String objectKey, File file) {
try {
ossClient.putObject(ossConfig.getBucket(), objectKey, file);
return R.ok(getInfo(objectKey), "文件上传成功");
} catch (Exception e) {
LOGGER.error("文件上传失败", e);
return R.fail("文件上传失败");
} finally {
if (!file.delete()) {
LOGGER.warn("临时文件删除失败");
}
}
}
/**
* 获取文件在OSS中的信息
*
* @param objectKey 文件路径
* @return 文件信息对象
*/
public OssInfo getInfo(String objectKey) {
try {
ObjectMetadata objectMetadata = ossClient.getObjectMetadata(ossConfig.getBucket(), objectKey);
return OssInfo.builder()
.name(FileUtils.getName(objectKey))
.bucketName(ossConfig.getBucket())
.fileType(objectMetadata.getContentType())
.length(Convert.toStr(objectMetadata.getContentLength()))
.path(objectKey).build();
} catch (Exception e) {
LOGGER.error("获取文件信息失败", e);
return OssInfo.builder().build();
}
}
/**
* 从OSS下载文件
*
* @param objectKey 文件路径
* @return OSSObject对象包含下载的文件
*/
public R<OSSObject> download(String objectKey) {
if (doesObjectExist(ossConfig.getBucket(), objectKey)) {
return R.fail("文件不存在");
}
try {
return R.ok(ossClient.getObject(ossConfig.getBucket(), objectKey));
} catch (Exception e) {
LOGGER.error("文件下载失败", e);
return R.fail("文件下载失败");
}
}
/**
* 删除OSS中的文件
*
* @param objectKey 文件路径
* @return 删除操作的结果
*/
public R<T> delete(String objectKey) {
try {
if (doesObjectExist(ossConfig.getBucket(), objectKey)) {
return R.fail("文件不存在");
}
ossClient.deleteObject(ossConfig.getBucket(), objectKey);
return R.ok(null,"文件删除成功");
} catch (Exception e) {
LOGGER.error("文件删除失败", e);
return R.fail("文件删除失败");
}
}
/**
* 检查OSS中是否存在指定的文件
*
* @param bucketName Bucket名称
* @param objectKey 文件路径
* @return 如果文件存在返回true否则返回false
*/
private boolean doesObjectExist(String bucketName, String objectKey) {
try {
return !ossClient.doesObjectExist(bucketName, objectKey);
} catch (Exception e) {
LOGGER.error("判断文件是否存在失败", e);
return true;
}
}
}

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/bonus-file" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.bonus" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@ -1,21 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bonus</groupId>
<artifactId>bonus-modules</artifactId>
<version>24.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bonus-mongodb</artifactId>
<artifactId>bonus-tcp</artifactId>
<description>
bonus-tcp 协议模块
</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
@ -42,23 +40,35 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- FastDFS -->
<!-- Swagger UI -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Minio -->
<!-- Mysql Connector -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- bonus Api System -->
<!-- bonus Common DataSource -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-api-system</artifactId>
<artifactId>bonus-common-datasource</artifactId>
</dependency>
<!-- bonus Common DataScope -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-datascope</artifactId>
</dependency>
<!-- bonus Common Log -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-log</artifactId>
</dependency>
<!-- bonus Common Swagger -->
@ -66,27 +76,33 @@
<groupId>com.bonus</groupId>
<artifactId>bonus-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.12</version> <!-- 版本号可以根据需要调整 -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--加密依赖包-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-entity</artifactId>
<version>24.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-entity</artifactId>
<version>24.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-security</artifactId>
<version>24.6.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
@ -105,4 +121,6 @@
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,19 @@
package com.bonus.tcp;
import com.bonus.common.security.annotation.EnableCustomConfig;
import com.bonus.common.security.annotation.EnableRyFeignClients;
import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
public class BonusTcpApplication {
public static void main(String[] args) {
SpringApplication.run(BonusTcpApplication.class, args);
System.err.println("(♥◠‿◠)ノ゙ TCP模块启动成功 ლ(´ڡ`ლ)゙");
}
}

View File

@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _
(_) | |
_ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___
| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \
| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | |
|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_|
__/ | __/ |
|___/ |___/

View File

@ -1,27 +1,27 @@
# Tomcat
server:
port: 9204
port: 21997
# Spring
spring:
application:
# 应用名称
name: bonus-oss
name: bonus-tcp
profiles:
# 环境配置
active: dev
cloud:
nacos:
username: nacos
password: nacos
password: Jjsp@nacos2023
discovery:
# 服务注册地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
server-addr: 127.0.0.1:8848
namespace: ljzhgd
config:
# 配置中心地址
server-addr: 192.168.0.14:8848
namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
server-addr: 127.0.0.1:8848
namespace: ljzhgd
# 配置文件格式
file-extension: yml
# 共享配置

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/bonus-file" />
<property name="log.path" value="logs/bonus-system" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

View File

@ -13,9 +13,9 @@
<module>bonus-gen</module>
<module>bonus-job</module>
<module>bonus-file</module>
<module>bonus-oss</module>
<module>bonus-app</module>
<module>bonus-bracelet</module>
<module>bonus-tcp</module>
</modules>
<artifactId>bonus-modules</artifactId>