package com.ard.oss.service.impl;
|
|
import com.ard.common.config.OssConfiguration;
|
import com.ard.common.exception.file.FileNameLengthLimitExceededException;
|
import com.ard.common.exception.file.FileSizeLimitExceededException;
|
import com.ard.common.exception.file.InvalidExtensionException;
|
import com.ard.common.utils.file.FileUploadUtils;
|
import com.ard.common.utils.file.MimeTypeUtils;
|
import com.ard.oss.model.CredentialsDTO;
|
import com.ard.oss.model.enums.OssTypeEnum;
|
import com.ard.oss.service.IOssService;
|
import io.minio.PutObjectArgs;
|
import lombok.Cleanup;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.net.URL;
|
import java.util.Arrays;
|
import java.util.List;
|
|
import static com.ard.common.utils.file.FileUploadUtils.assertAllowed;
|
import static com.ard.common.utils.file.FileUploadUtils.extractFilename;
|
|
/**
|
* @author sean
|
* @version 1.0
|
* @date 2022/5/30
|
*/
|
@Service
|
public class OssServiceContext {
|
|
private IOssService ossService;
|
|
@Autowired
|
public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) {
|
if (!OssConfiguration.enable) {
|
return;
|
}
|
this.ossService = ossServices.stream()
|
.filter(ossService -> ossService.getOssType().equals(OssConfiguration.provider))
|
.findFirst()
|
.orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " +
|
Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray())));
|
}
|
|
IOssService getOssService() {
|
return this.ossService;
|
}
|
|
public CredentialsDTO getCredentials() {
|
return this.ossService.getCredentials();
|
}
|
|
public URL getObjectUrl(String bucket, String objectKey) {
|
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
|
throw new IllegalArgumentException();
|
}
|
return this.ossService.getObjectUrl(bucket, objectKey);
|
}
|
|
public Boolean deleteObject(String bucket, String objectKey) {
|
return this.ossService.deleteObject(bucket, objectKey);
|
}
|
|
public InputStream getObject(String bucket, String objectKey) {
|
return this.ossService.getObject(bucket, objectKey);
|
}
|
|
public void putObject(String bucket, String objectKey, InputStream stream) {
|
this.ossService.putObject(bucket, objectKey, stream);
|
}
|
|
|
void createClient() {
|
this.ossService.createClient();
|
}
|
|
/**
|
* 以默认BucketName配置上传到Minio服务器
|
*
|
* @param file 上传的文件
|
* @return 文件名称
|
* @throws Exception
|
*/
|
public String upload(MultipartFile file) throws IOException {
|
try {
|
return upload(OssConfiguration.bucket, file);
|
} catch (Exception e) {
|
throw new IOException(e.getMessage(), e);
|
}
|
}
|
|
/**
|
* 自定义bucketName配置上传到Minio服务器
|
*
|
* @param file 上传的文件
|
* @return 文件名称
|
* @throws Exception
|
*/
|
public String upload(String bucket, MultipartFile file) throws IOException {
|
try {
|
return upload(bucket, null, file);
|
} catch (Exception e) {
|
throw new IOException(e.getMessage(), e);
|
}
|
}
|
|
/**
|
* ✅ 通用上传方法:
|
* - bucket 必传
|
* - object 可选(为空则自动生成)
|
* - 返回永久访问 URL
|
*/
|
public String upload(String bucket, String object, MultipartFile file) throws IOException {
|
try {
|
// 校验文件名长度
|
int fileNameLength = file.getOriginalFilename().length();
|
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
|
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
|
}
|
|
// 检查文件扩展名是否合法
|
assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
|
|
// ✅ 如果 object 为空,则自动生成文件名
|
String objectName = (object == null || object.isEmpty())
|
? extractFilename(file)
|
: object;
|
|
// 通过文件扩展名获取 MIME 类型
|
String contentType = getMimeTypeByExtension(file.getOriginalFilename());
|
|
@Cleanup
|
InputStream inputStream = file.getInputStream();
|
// 上传文件到 Minio
|
this.ossService.putObject(bucket, objectName, inputStream, contentType);
|
|
// ✅ 拼接永久 URL(不带 presigned 过期参数)
|
String baseUrl = OssConfiguration.endpoint;
|
if (!baseUrl.endsWith("/")) {
|
baseUrl += "/";
|
}
|
|
return baseUrl + bucket + "/" + objectName;
|
} catch (Exception e) {
|
throw new IOException("Upload failed: " + e.getMessage(), e);
|
}
|
}
|
|
public String upload(String bucket, String objectKey, InputStream input) {
|
try {
|
|
// 上传文件
|
this.ossService.putObject(bucket, objectKey, input);
|
|
// ✅ 构建永久访问 URL
|
String baseUrl = OssConfiguration.endpoint;
|
if (!baseUrl.endsWith("/")) {
|
baseUrl += "/";
|
}
|
return baseUrl + bucket + "/" + objectKey;
|
} catch (Exception e) {
|
throw new RuntimeException("Upload failed: " + e.getMessage(), e);
|
}
|
}
|
|
// 获取文件 MIME 类型
|
public String getMimeTypeByExtension(String fileName) {
|
// 获取文件扩展名
|
String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
|
// 根据文件扩展名返回 MIME 类型
|
switch (extension) {
|
case "jpg":
|
case "jpeg":
|
return "image/jpeg";
|
case "png":
|
return "image/png";
|
case "gif":
|
return "image/gif";
|
case "pdf":
|
return "application/pdf";
|
case "txt":
|
return "text/plain";
|
case "html":
|
return "text/html";
|
case "json":
|
return "application/json";
|
case "csv":
|
return "text/csv";
|
case "zip":
|
return "application/zip";
|
// 添加更多的扩展名映射
|
default:
|
return "application/octet-stream"; // 默认 MIME 类型
|
}
|
}
|
|
}
|