文字转语音

This commit is contained in:
spllzh
2025-10-04 19:52:06 +08:00
parent 24c00c22ab
commit 06730b656e
51 changed files with 5157 additions and 8 deletions

View File

@@ -0,0 +1,531 @@
package com.rj.utils;
import com.rj.config.MinIOConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* MinIO 工具类
* 提供文件上传、下载、删除等常用操作
*
* @author rj
* @date 2025-10-02
*/
@Slf4j
@Component
public class MinIOUtil {
@Autowired
private MinioClient minioClient;
@Autowired
private MinIOConfig minioConfig;
/**
* 检查存储桶是否存在
*
* @param bucketName 存储桶名称
* @return 是否存在
*/
public boolean bucketExists(String bucketName) {
try {
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
log.error("检查存储桶是否存在失败: {}", e.getMessage());
return false;
}
}
/**
* 创建存储桶
*
* @param bucketName 存储桶名称
* @return 是否创建成功
*/
public boolean createBucket(String bucketName) {
try {
if (!bucketExists(bucketName)) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
log.info("存储桶创建成功: {}", bucketName);
return true;
}
log.info("存储桶已存在: {}", bucketName);
return true;
} catch (Exception e) {
log.error("创建存储桶失败: {}", e.getMessage());
return false;
}
}
/**
* 获取所有存储桶
*
* @return 存储桶列表
*/
public List<String> getAllBuckets() {
try {
List<Bucket> buckets = minioClient.listBuckets();
List<String> bucketNames = new ArrayList<>();
for (Bucket bucket : buckets) {
bucketNames.add(bucket.name());
}
return bucketNames;
} catch (Exception e) {
log.error("获取存储桶列表失败: {}", e.getMessage());
return new ArrayList<>();
}
}
/**
* 删除存储桶
*
* @param bucketName 存储桶名称
* @return 是否删除成功
*/
public boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
log.info("存储桶删除成功: {}", bucketName);
return true;
} catch (Exception e) {
log.error("删除存储桶失败: {}", e.getMessage());
return false;
}
}
/**
* 上传文件
*
* @param file 文件
* @param bucketName 存储桶名称
* @return 文件名
*/
public String uploadFile(MultipartFile file, String bucketName) {
return uploadFile(file, bucketName, null);
}
/**
* 上传文件
*
* @param file 文件
* @param bucketName 存储桶名称
* @param objectName 对象名称文件名如果为null则自动生成
* @return 文件名
*/
public String uploadFile(MultipartFile file, String bucketName, String objectName) {
try {
// 确保存储桶存在
createBucket(bucketName);
// 生成文件名
if (objectName == null || objectName.trim().isEmpty()) {
objectName = generateFileName(file.getOriginalFilename());
}
// 上传文件
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
log.info("文件上传成功: {}/{}", bucketName, objectName);
return objectName;
} catch (Exception e) {
log.error("文件上传失败: {}", e.getMessage());
throw new RuntimeException("文件上传失败: " + e.getMessage());
}
}
/**
* 上传文件流
*
* @param inputStream 文件流
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param contentType 内容类型
* @return 是否上传成功
*/
public boolean uploadFile(InputStream inputStream, String bucketName, String objectName, String contentType) {
try {
createBucket(bucketName);
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(inputStream, -1, 10485760) // 10MB
.contentType(contentType)
.build()
);
log.info("文件流上传成功: {}/{}", bucketName, objectName);
return true;
} catch (Exception e) {
log.error("文件流上传失败: {}", e.getMessage());
return false;
}
}
/**
* 上传字节数组
*
* @param data 字节数组
* @param objectName 对象名称
* @param contentType 内容类型
* @return 对象名称
*/
public String uploadFile(byte[] data, String objectName, String contentType) {
try {
// 使用配置中的默认存储桶
String bucketName = minioConfig.getBucketName();
// 确保存储桶存在
createBucket(bucketName);
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(new java.io.ByteArrayInputStream(data), data.length, -1)
.contentType(contentType)
.build()
);
log.info("字节数组上传成功: {}/{}, 大小: {} bytes", bucketName, objectName, data.length);
return objectName;
} catch (Exception e) {
log.error("字节数组上传失败: {}", e.getMessage());
throw new RuntimeException("字节数组上传失败: " + e.getMessage());
}
}
/**
* 下载文件
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 文件流
*/
public InputStream downloadFile(String bucketName, String objectName) {
try {
return minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
} catch (Exception e) {
log.error("文件下载失败: {}", e.getMessage());
throw new RuntimeException("文件下载失败: " + e.getMessage());
}
}
/**
* 下载文件到本地
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param fileName 本地文件路径
* @return 是否下载成功
*/
public boolean downloadFile(String bucketName, String objectName, String fileName) {
try {
minioClient.downloadObject(
DownloadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(fileName)
.build()
);
log.info("文件下载成功: {}/{} -> {}", bucketName, objectName, fileName);
return true;
} catch (Exception e) {
log.error("文件下载失败: {}", e.getMessage());
return false;
}
}
/**
* 删除文件
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 是否删除成功
*/
public boolean removeFile(String bucketName, String objectName) {
try {
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
log.info("文件删除成功: {}/{}", bucketName, objectName);
return true;
} catch (Exception e) {
log.error("文件删除失败: {}", e.getMessage());
return false;
}
}
/**
* 获取文件信息
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 文件信息
*/
public StatObjectResponse getFileInfo(String bucketName, String objectName) {
try {
return minioClient.statObject(
StatObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
} catch (Exception e) {
log.error("获取文件信息失败: {}", e.getMessage());
return null;
}
}
/**
* 获取文件列表
*
* @param bucketName 存储桶名称
* @return 文件列表
*/
public List<String> listFiles(String bucketName) {
return listFiles(bucketName, null);
}
/**
* 获取文件列表
*
* @param bucketName 存储桶名称
* @param prefix 文件前缀
* @return 文件列表
*/
public List<String> listFiles(String bucketName, String prefix) {
List<String> files = new ArrayList<>();
try {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(prefix)
.build()
);
for (Result<Item> result : results) {
Item item = result.get();
files.add(item.objectName());
}
} catch (Exception e) {
log.error("获取文件列表失败: {}", e.getMessage());
}
return files;
}
/**
* 获取文件详细列表
*
* @param bucketName 存储桶名称
* @return 文件详细信息列表
*/
public List<FileInfo> listFileDetails(String bucketName) {
return listFileDetails(bucketName, null);
}
/**
* 获取文件详细列表
*
* @param bucketName 存储桶名称
* @param prefix 文件前缀
* @return 文件详细信息列表
*/
public List<FileInfo> listFileDetails(String bucketName, String prefix) {
List<FileInfo> files = new ArrayList<>();
try {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(prefix)
.build()
);
for (Result<Item> result : results) {
Item item = result.get();
FileInfo fileInfo = new FileInfo();
fileInfo.setObjectName(item.objectName());
fileInfo.setSize(item.size());
fileInfo.setLastModified(item.lastModified());
fileInfo.setEtag(item.etag());
files.add(fileInfo);
}
} catch (Exception e) {
log.error("获取文件详细列表失败: {}", e.getMessage());
}
return files;
}
/**
* 获取文件预签名URL用于临时访问
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param expires 过期时间(秒)
* @return 预签名URL
*/
public String getPresignedObjectUrl(String bucketName, String objectName, int expires) {
try {
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.expiry(expires, TimeUnit.SECONDS)
.build()
);
} catch (Exception e) {
log.error("获取预签名URL失败: {}", e.getMessage());
return null;
}
}
/**
* 获取文件预签名URL默认7天过期
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 预签名URL
*/
public String getPresignedObjectUrl(String bucketName, String objectName) {
return getPresignedObjectUrl(bucketName, objectName, 7 * 24 * 3600); // 7天
}
/**
* 复制文件
*
* @param sourceBucketName 源存储桶名称
* @param sourceObjectName 源对象名称
* @param targetBucketName 目标存储桶名称
* @param targetObjectName 目标对象名称
* @return 是否复制成功
*/
public boolean copyFile(String sourceBucketName, String sourceObjectName,
String targetBucketName, String targetObjectName) {
try {
createBucket(targetBucketName);
minioClient.copyObject(
CopyObjectArgs.builder()
.bucket(targetBucketName)
.object(targetObjectName)
.source(CopySource.builder()
.bucket(sourceBucketName)
.object(sourceObjectName)
.build())
.build()
);
log.info("文件复制成功: {}/{} -> {}/{}",
sourceBucketName, sourceObjectName, targetBucketName, targetObjectName);
return true;
} catch (Exception e) {
log.error("文件复制失败: {}", e.getMessage());
return false;
}
}
/**
* 生成唯一文件名
*
* @param originalFilename 原始文件名
* @return 唯一文件名
*/
private String generateFileName(String originalFilename) {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
String uuid = UUID.randomUUID().toString().replace("-", "");
String extension = "";
if (originalFilename != null && originalFilename.contains(".")) {
extension = originalFilename.substring(originalFilename.lastIndexOf("."));
}
return timestamp + "_" + uuid + extension;
}
/**
* 文件信息类
*/
public static class FileInfo {
private String objectName;
private Long size;
private java.time.ZonedDateTime lastModified;
private String etag;
// Getters and Setters
public String getObjectName() {
return objectName;
}
public void setObjectName(String objectName) {
this.objectName = objectName;
}
public Long getSize() {
return size;
}
public void setSize(Long size) {
this.size = size;
}
public java.time.ZonedDateTime getLastModified() {
return lastModified;
}
public void setLastModified(java.time.ZonedDateTime lastModified) {
this.lastModified = lastModified;
}
public String getEtag() {
return etag;
}
public void setEtag(String etag) {
this.etag = etag;
}
@Override
public String toString() {
return "FileInfo{" +
"objectName='" + objectName + '\'' +
", size=" + size +
", lastModified=" + lastModified +
", etag='" + etag + '\'' +
'}';
}
}
}