This commit is contained in:
jack ning
2025-07-27 22:48:48 +08:00
parent e5f10ed22c
commit 810b41fd99
6 changed files with 135 additions and 12 deletions

View File

@@ -19,10 +19,17 @@ import java.net.URL;
import java.nio.file.Files;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.SetBucketPolicyArgs;
import com.bytedesk.core.config.properties.BytedeskProperties;
import com.bytedesk.core.utils.BdDateUtils;
@@ -43,13 +50,66 @@ import lombok.extern.slf4j.Slf4j;
*/
@Slf4j
@Component
@ConditionalOnProperty(name = "bytedesk.minio.enabled", havingValue = "true", matchIfMissing = false)
public class UploadMinioService {
@Autowired
private BytedeskProperties bytedeskProperties;
@Autowired
private MinioClient minioClient;
/**
* 初始化 MinIO 存储桶和策略
*/
@PostConstruct
public void initMinio() {
try {
String bucketName = bytedeskProperties.getMinioBucketName();
// 检查存储桶是否存在,如果不存在则创建
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!bucketExists) {
log.info("创建 MinIO 存储桶: {}", bucketName);
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
// 设置存储桶策略为公开读取
String bucketPolicy = String.format("""
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::%s/*"
]
}
]
}
""", bucketName);
log.info("设置 MinIO 存储桶 {} 为公开读取", bucketName);
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(bucketPolicy)
.build()
);
log.info("MinIO 初始化完成,存储桶: {}, 策略: 公开读取", bucketName);
} catch (Exception e) {
log.error("MinIO 初始化失败: {}", e.getMessage(), e);
}
}
/**
* 上传文件到 MinIO
*

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-15 11:35:53
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-07-27 22:08:46
* @LastEditTime: 2025-07-27 22:35:52
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -28,6 +28,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.data.domain.Page;
@@ -35,6 +36,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;
import com.bytedesk.core.base.BaseRestService;
@@ -48,13 +50,13 @@ import com.bytedesk.core.upload.storage.UploadStorageFileNotFoundException;
import com.bytedesk.core.utils.BdDateUtils;
import com.bytedesk.core.utils.ConvertUtils;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
// https://spring.io/guides/gs/uploading-files
@Slf4j
@Service
@AllArgsConstructor
@RequiredArgsConstructor
public class UploadRestService extends BaseRestService<UploadEntity, UploadRequest, UploadResponse> {
private final Path uploadDir;
@@ -71,6 +73,7 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
private final UploadWatermarkService uploadWatermarkService;
@Autowired(required = false)
private final UploadMinioService uploadMinioService;
@Override
@@ -311,9 +314,9 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
}
// 删除整个上传文件夹,危险操作,暂时注释掉
// public void deleteAll() {
// FileSystemUtils.deleteRecursively(uploadDir.toFile());
// }
public void deleteAll() {
FileSystemUtils.deleteRecursively(uploadDir.toFile());
}
@Override
public void deleteByUid(String uid) {
@@ -352,8 +355,18 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
userProtobuf = ConvertUtils.convertToUserProtobuf(user);
request.setUserUid(user.getUid());
request.setOrgUid(user.getOrgUid());
}
String fileUrl = store(file, request.getFileName(), request);
}
// 根据配置选择存储方式:优先使用 MinIO否则使用本地文件系统
String fileUrl;
if (bytedeskProperties.getMinioEnabled()) {
log.info("MinIO 已启用,使用 MinIO 存储文件");
fileUrl = storeToMinio(file, request.getFileName(), request);
} else {
log.info("MinIO 未启用,使用本地文件系统存储文件");
fileUrl = store(file, request.getFileName(), request);
}
request.setFileUrl(fileUrl);
request.setType(request.getKbType());
request.setUser(userProtobuf.toJson());
@@ -377,6 +390,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
throw new RuntimeException("MinIO 存储未启用,请在配置中启用 bytedesk.minio.enabled=true");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
try {
if (file.isEmpty()) {
throw new UploadStorageException("Failed to store empty file.");
@@ -411,6 +429,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
throw new RuntimeException("MinIO 存储未启用,请在配置中启用 bytedesk.minio.enabled=true");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
try {
File localFile = new File(localFilePath);
if (!localFile.exists()) {
@@ -446,6 +469,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
throw new RuntimeException("MinIO 存储未启用,请在配置中启用 bytedesk.minio.enabled=true");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
try {
// 根据文件类型选择存储文件夹
String folder = getMinioFolderByFileName(fileName, request);
@@ -577,6 +605,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
if (!bytedeskProperties.getMinioEnabled()) {
throw new RuntimeException("MinIO 存储未启用");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
try {
uploadMinioService.deleteFile(objectPath);
@@ -597,6 +630,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
if (!bytedeskProperties.getMinioEnabled()) {
return false;
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
return false;
}
return uploadMinioService.fileExists(objectPath);
}
@@ -612,6 +650,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
if (!bytedeskProperties.getMinioEnabled()) {
throw new RuntimeException("MinIO 存储未启用");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
return uploadMinioService.getDownloadUrl(objectPath, expiry);
}
@@ -627,6 +670,11 @@ public class UploadRestService extends BaseRestService<UploadEntity, UploadReque
if (!bytedeskProperties.getMinioEnabled()) {
throw new RuntimeException("MinIO 存储未启用");
}
// 检查 MinIO 服务是否可用
if (uploadMinioService == null) {
throw new RuntimeException("MinIO 服务未初始化,请检查配置");
}
return uploadMinioService.getUploadUrl(objectPath, expiry);
}

View File

@@ -11,13 +11,14 @@ import java.nio.file.StandardCopyOption;
import javax.imageio.ImageIO;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.bytedesk.core.upload.watermark.WatermarkConfig;
import com.bytedesk.core.upload.watermark.WatermarkService;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
@@ -26,10 +27,12 @@ import lombok.extern.slf4j.Slf4j;
*/
@Slf4j
@Service
@AllArgsConstructor
@RequiredArgsConstructor
@ConditionalOnProperty(name = "bytedesk.watermark.enabled", havingValue = "true", matchIfMissing = false)
public class UploadWatermarkService {
private final WatermarkService watermarkService;
private final WatermarkConfig watermarkConfig;
/**

View File

@@ -14,14 +14,18 @@
package com.bytedesk.core.upload.cloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bytedesk.core.config.properties.BytedeskProperties;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
@ConditionalOnProperty(name = "bytedesk.minio.enabled", havingValue = "true", matchIfMissing = false)
public class MinioConfig {
@Autowired
@@ -32,10 +36,16 @@ public class MinioConfig {
*/
@Bean
public MinioClient getMinioClient() {
log.info("初始化 MinIO 客户端: endpoint={}, bucket={}",
bytedeskProperties.getMinioEndpoint(),
bytedeskProperties.getMinioBucketName());
MinioClient minioClient = MinioClient.builder()
.endpoint(bytedeskProperties.getMinioEndpoint())
.credentials(bytedeskProperties.getMinioAccessKey(), bytedeskProperties.getMinioSecretKey())
.build();
log.info("MinIO 客户端初始化成功");
return minioClient;
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-01-27 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-25 17:25:45
* @LastEditTime: 2025-07-27 22:37:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-01-27 10:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-06-25 17:29:00
* @LastEditTime: 2025-07-27 22:37:12
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -25,6 +25,7 @@ import java.nio.file.StandardCopyOption;
import javax.imageio.ImageIO;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@@ -35,6 +36,7 @@ import lombok.extern.slf4j.Slf4j;
*/
@Slf4j
@Service
@ConditionalOnProperty(name = "bytedesk.watermark.enabled", havingValue = "true", matchIfMissing = false)
public class WatermarkService {
/**