package com.ard.ossdock.service.impl; import com.ard.ossdock.config.OssDockConfiguration; import com.ard.common.exception.file.FileNameLengthLimitExceededException; import com.ard.common.utils.file.FileUploadUtils; import com.ard.common.utils.file.MimeTypeUtils; import com.ard.ossdock.model.CredentialsDockDTO; import com.ard.ossdock.model.enums.OssDockTypeEnum; import com.ard.ossdock.service.IOssDockService; 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 OssDockServiceContext { private IOssDockService ossService; @Autowired public OssDockServiceContext(List ossServices, OssDockConfiguration configuration) { if (!OssDockConfiguration.enable) { return; } this.ossService = ossServices.stream() .filter(ossService -> ossService.getOssType().equals(OssDockConfiguration.provider)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " + Arrays.toString(Arrays.stream(OssDockTypeEnum.values()).map(OssDockTypeEnum::getType).toArray()))); } IOssDockService getOssService() { return this.ossService; } public CredentialsDockDTO 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(OssDockConfiguration.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); return buildUrl(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); return buildUrl(bucket, objectKey); } catch (Exception e) { throw new RuntimeException("Upload failed: " + e.getMessage(), e); } } public String upload(String bucket, String objectKey, InputStream input, String contentType) { try { // 上传文件时指定 Content-Type this.ossService.putObject(bucket, objectKey, input, contentType); return buildUrl(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 类型 } } // 构建url private String buildUrl(String bucket, String key) { String base = OssDockConfiguration.endpoint; if (!base.endsWith("/")) { base += "/"; } return base + bucket + "/" + key; } }