liding
11 小时以前 71fba5328a35b449b11088e540932787220f91d8
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MinioUtils.java
@@ -9,6 +9,8 @@
import io.minio.http.Method;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -16,15 +18,11 @@
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -303,4 +301,140 @@
        return null;
    }
    /**
     * 下载url(强制浏览器下载文件)
     * @param bucketFileName minio文件名称
     * @param bucketName 存储桶名称
     * @param  (小时),默认24小时
     * @return 文件下载URL
     */
    public String getDownloadUrl(String bucketFileName, String bucketName) {
        if (StringUtils.isNotBlank(bucketFileName)) {
            try {
                // 检查文件是否存在
                minioClient.statObject(StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(bucketFileName)
                        .build());
                // 设置响应头
                Map<String, String> reqParams = new HashMap<>();
                // 提取原始文件名(如果存储时保留了原始名称)
                String originalFileName = extractOriginalFileName(bucketFileName);
                reqParams.put("response-content-disposition",
                        "attachment; filename=\"" + URLEncoder.encode(originalFileName, StandardCharsets.UTF_8) + "\"");
                // 构建预签名URL参数
                GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(bucketFileName)
                        .expiry(previewExpiry, TimeUnit.HOURS)
                        .extraQueryParams(reqParams)
                        .build();
                return minioClient.getPresignedObjectUrl(args);
            } catch (Exception e) {
                throw new UtilException("MinioUtils:生成下载链接异常", e);
            }
        }
        return null;
    }
    /**
     * 从bucketFileName中提取原始文件名
     * 需根据实际存储规则调整(例如,如果存储时添加了时间戳或UUID后缀)
     */
    private String extractOriginalFileName(String bucketFileName) {
        // 示例:如果存储格式为 "原始文件名_UUID"
        int underscoreIndex = bucketFileName.lastIndexOf("_");
        if (underscoreIndex > 0) {
            return bucketFileName.substring(0, underscoreIndex);
        }
        // 如果没有特殊格式,直接返回完整文件名
        return bucketFileName;
    }
    /**
     * 生成预览URL
     * @param bucketFilename 文件在MinIO中的唯一标识
     * @param bucketName 存储桶名称
     * @param useDefaultExpiry 是否使用默认过期时间(true=使用默认过期时间,false=永久有效)
     * @return 预览URL
     */
    public String getPreviewUrls(String bucketFilename, String bucketName, boolean useDefaultExpiry) {
        if (StringUtils.isBlank(bucketFilename)) {
            return null;
        }
        try {
            // 验证文件存在性
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(bucketFilename)
                    .build());
            GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(bucketFilename);
            // 设置过期时间:useDefaultExpiry=true 使用配置的过期时间
            if (useDefaultExpiry) {
                builder.expiry(previewExpiry, TimeUnit.HOURS);
            }
            return minioClient.getPresignedObjectUrl(builder.build());
        } catch (Exception e) {
            throw new UtilException("生成预览URL失败: " + e.getMessage(), e);
        }
    }
    /**
     * 生成下载URL(强制浏览器下载)
     * @param bucketFilename 文件在MinIO中的唯一标识
     * @param bucketName 存储桶名称
     * @param originalFileName 原始文件名(用于下载时显示)
     * @param useDefaultExpiry 是否使用默认过期时间(true=使用默认,false=无过期时间)
     * @return 下载URL
     */
    public String getDownloadUrls(String bucketFilename, String bucketName, String originalFileName, boolean useDefaultExpiry) {
        if (StringUtils.isBlank(bucketFilename)) {
            return null;
        }
        try {
            // 验证文件存在性
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(bucketFilename)
                    .build());
            // 正确编码文件名:替换 + 为 %20
            String encodedFileName = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8)
                    .replace("+", "%20");
            Map<String, String> reqParams = new HashMap<>();
            reqParams.put("response-content-disposition",
                    "attachment; filename=\"" + encodedFileName + "\"");
            GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(bucketFilename)
                    .extraQueryParams(reqParams);
            // 根据参数决定是否设置过期时间
            if (useDefaultExpiry) {
                // 使用默认过期时间(从配置读取)
                builder.expiry(previewExpiry, TimeUnit.HOURS);
            } else {
                // 不设置过期时间(MinIO 默认7天)
            }
            return minioClient.getPresignedObjectUrl(builder.build());
        } catch (Exception e) {
            throw new UtilException("生成下载URL失败: " + e.getMessage(), e);
        }
    }
}