前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >02-SpringBoot集成MinIo

02-SpringBoot集成MinIo

作者头像
彼岸舞
发布2022-08-24 08:36:20
1.9K0
发布2022-08-24 08:36:20
举报
文章被收录于专栏:java开发的那点事

添加依赖

代码语言:javascript
复制
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>
<dependency>
  <groupId>net.coobird</groupId>
  <artifactId>thumbnailator</artifactId>
  <version>0.4.8</version>
</dependency>
<dependency>
  <groupId>io.minio</groupId>
  <artifactId>minio</artifactId>
  <version>8.3.4</version>
</dependency>
<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>okhttp</artifactId>
  <version>4.8.1</version>
</dependency>

新增yml配置

代码语言:javascript
复制
min:
  io:
    endpoint: http://192.168.247.130:9000
    accessKey: admin
    secretKey: password
    bucket: images
    imageType: .jpeg
spring:
  servlet:
    multipart:
      max-file-size: 5MB
      max-request-size: 15MB

新建配置类

代码语言:javascript
复制
package com.jd.emergencydepartment.config;

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Data
@Component
public class MinIoConfig {

    @Value("${min.io.endpoint}")
    private String endpoint;

    @Value("${min.io.accessKey}")
    private String accessKey;

    @Value("${min.io.secretKey}")
    private String secretKey;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder().endpoint(endpoint).credentials(accessKey,secretKey).build();
    }

}

新建工具类

代码语言:javascript
复制
package com.jd.minio;

import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Component
public class MinIoUtils {

    @Resource
    private MinioClient client;

    private static final String SEPARATOR_DOT = ".";

    private static final String SEPARATOR_ACROSS = "-";

    private static final String SEPARATOR_STR = "";

    // 存储桶名称
    private static final String chunkBucKet = "img";

    /**
     * 不排序
     */
    public final static boolean NOT_SORT = false;

    /**
     * 排序
     */
    public final static boolean SORT = true;

    /**
     * 默认过期时间(分钟)
     */
    private final static Integer DEFAULT_EXPIRY = 60;

    /**
     * 删除分片
     */
    public final static boolean DELETE_CHUNK_OBJECT = true;
    /**
     * 不删除分片
     */
    public final static boolean NOT_DELETE_CHUNK_OBJECT = false;

    /**
     * @param bucketName
     * @return boolean
     * @Description 判断 bucket是否存在
     * @author exe.wangtaotao
     * @date 2020/10/21 16:33
     */
    public boolean bucketExists(String bucketName) {
        try {
            return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 创建存储桶
     * 创建 bucket
     *
     * @param bucketName
     */
    public void makeBucket(String bucketName) {
        try {
            boolean isExist = bucketExists(bucketName);
            if (!isExist) {
                client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param
     * @return java.util.List<java.lang.String>
     * @Description 获取文件存储服务的所有存储桶名称
     * @author exe.wangtaotao
     * @date 2020/10/21 16:35
     */
    public List<String> listBucketNames() {
        List<Bucket> bucketList = listBuckets();
        List<String> bucketListName = new ArrayList<>();
        for (Bucket bucket : bucketList) {
            bucketListName.add(bucket.name());
        }
        return bucketListName;
    }

    /**
     * @return java.util.List<io.minio.messages.Bucket>
     * @Description 列出所有存储桶
     */
    @SneakyThrows
    private List<Bucket> listBuckets() {
        return client.listBuckets();
    }


    /**
     * 获取对象文件名称列表
     *
     * @param bucketName 存储桶名称
     * @param prefix     对象名称前缀(文件夹 /xx/xx/xxx.jpg 中的 /xx/xx/)
     * @return objectNames
     */
    public List<String> listObjectNames(String bucketName, String prefix) {
        return listObjectNames(bucketName, prefix, NOT_SORT);
    }


    /**
     * 获取对象文件名称列表
     *
     * @param bucketName 存储桶名称
     * @param prefix     对象名称前缀(文件夹 /xx/xx/xxx.jpg 中的 /xx/xx/)
     * @param sort       是否排序(升序)
     * @return objectNames
     */
    @SneakyThrows
    public List<String> listObjectNames(String bucketName, String prefix, Boolean sort) {

        boolean flag = bucketExists(bucketName);
        if (flag) {

            ListObjectsArgs listObjectsArgs;
            if (null == prefix) {
                listObjectsArgs = ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .recursive(true)
                        .build();
            } else {
                listObjectsArgs = ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(prefix)
                        .recursive(true)
                        .build();
            }
            Iterable<io.minio.Result<Item>> chunks = client.listObjects(listObjectsArgs);
            List<String> chunkPaths = new ArrayList<>();
            for (io.minio.Result<Item> item : chunks) {
                chunkPaths.add(item.get().objectName());
            }
            if (sort) {
                chunkPaths.sort(new Str2IntComparator(false));
            }
            return chunkPaths;
        }
        return new ArrayList<>();
    }

    /**
     * 在桶下创建文件夹,文件夹层级结构根据参数决定
     *
     * @param bucket 桶名称
     * @param WotDir 格式为 xxx/xxx/xxx/
     */
    @SneakyThrows
    public String createDirectory(String bucket, String WotDir) {
        if (!this.bucketExists(bucket)) {
            return null;
        }
        client.putObject(PutObjectArgs.builder().bucket(bucket).object(WotDir).stream(
                        new ByteArrayInputStream(new byte[]{}), 0, -1)
                .build());
        return WotDir;
    }


    /**
     * 删除一个文件
     *
     * @param bucketName
     * @param objectName
     */
    @SneakyThrows
    public boolean removeObject(String bucketName, String objectName) {

        if (!bucketExists(bucketName)) {
            return false;
        }
        client.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
        return true;
    }

    /**
     * @param bucketName
     * @param objectNames
     * @return java.util.List<java.lang.String>
     * @Description 删除指定桶的多个文件对象, 返回删除错误的对象列表,全部删除成功,返回空列表
     * @author exe.wangtaotao
     * @date 2020/10/21 16:43
     */
    @SneakyThrows
    public List<String> removeObjects(String bucketName, List<String> objectNames) {
        if (!bucketExists(bucketName)) {
            return new ArrayList<>();
        }
        List<DeleteObject> deleteObjects = new ArrayList<>(objectNames.size());
        for (String objectName : objectNames) {
            deleteObjects.add(new DeleteObject(objectName));
        }
        List<String> deleteErrorNames = new ArrayList<>();
        Iterable<io.minio.Result<DeleteError>> results = client.removeObjects(
                RemoveObjectsArgs.builder()
                        .bucket(bucketName)
                        .objects(deleteObjects)
                        .build());
        for (io.minio.Result<DeleteError> result : results) {
            DeleteError error = result.get();
            deleteErrorNames.add(error.objectName());
        }
        return deleteErrorNames;
    }


    /**
     * 获取访问对象的外链地址
     * 获取文件的下载url
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @param expiry     过期时间(分钟) 最大为7天 超过7天则默认最大值
     * @return viewUrl
     */
    @SneakyThrows
    public String getObjectUrl(String bucketName, String objectName, Integer expiry) {
        expiry = expiryHandle(expiry);
        return client.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expiry)
                        .build()
        );
    }


    /**
     * 创建上传文件对象的外链
     *
     * @param bucketName 存储桶名称
     * @param objectName 欲上传文件对象的名称
     * @return uploadUrl
     */
    public String createUploadUrl(String bucketName, String objectName) {
        return createUploadUrl(bucketName, objectName, DEFAULT_EXPIRY);
    }

    /**
     * 创建上传文件对象的外链
     *
     * @param bucketName 存储桶名称
     * @param objectName 欲上传文件对象的名称
     * @param expiry     过期时间(分钟) 最大为7天 超过7天则默认最大值
     * @return uploadUrl
     */
    @SneakyThrows
    public String createUploadUrl(String bucketName, String objectName, Integer expiry) {
        expiry = expiryHandle(expiry);
        return client.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.PUT)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expiry)
                        .build()
        );
    }

    /**
     * 文件下载
     *
     * @param fileName 文件名
     * @return InputStream
     */
    public void downLoadFile(HttpServletResponse response,String fileName) {
       /* InputStream inputStream = null;
        try {
            StatObjectResponse statObjectResponse = client.statObject(StatObjectArgs.builder().bucket(chunkBucKet).object(fileName).build());
            if (statObjectResponse.size() > 0) {
                inputStream = client.getObject(GetObjectArgs.builder().bucket(chunkBucKet).object(fileName).build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return inputStream;*/
        try(InputStream ism = new BufferedInputStream(client.getObject(GetObjectArgs.builder()
                .bucket(chunkBucKet)
                .object(fileName).build()))) {
            // 调用statObject()来判断对象是否存在。
            // 如果不存在, statObject()抛出异常,
            // 否则则代表对象存在
            client.statObject(StatObjectArgs.builder()
                    .bucket(chunkBucKet)
                    .object(fileName).build());
            byte buf[] = new byte[1024];
            int length = 0;
            response.reset();
            //Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
            // Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,
            // 文件直接在浏览器上显示或者在访问时弹出文件下载对话框。
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setContentType("application/x-msdownload");
            response.setCharacterEncoding("utf-8");
            OutputStream osm = new BufferedOutputStream(response.getOutputStream());
            while ((length = ism.read(buf))>0) {
                osm.write(buf,0, length);
            }
            osm.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 批量下载
     *
     * @param directory
     * @return
     */
    @SneakyThrows
    public List<String> downLoadMore(String bucket, String directory) {
        Iterable<io.minio.Result<Item>> objs = client.listObjects(ListObjectsArgs.builder().bucket(bucket).prefix(directory).useUrlEncodingType(false).build());
        List<String> list = new ArrayList<>();
        for (io.minio.Result<Item> result : objs) {
            String objectName = null;
            objectName = result.get().objectName();
            StatObjectResponse statObject = client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build());
            if (statObject != null && statObject.size() > 0) {
                String fileurl = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucket).object(statObject.object()).method(Method.GET).build());
                list.add(fileurl);
            }
        }
        return list;
    }


    /**
     * @param multipartFile
     * @param bucketName
     * @param directory image/
     * @return java.lang.String
     * @Description 文件上传
     * @author exe.wangtaotao
     * @date 2020/10/21 13:45
     */
    public MinIoUploadResDTO upload(MultipartFile multipartFile, String bucketName, String directory) throws Exception {
        if (!this.bucketExists(bucketName)) {
            this.makeBucket(bucketName);
        }
        InputStream inputStream = multipartFile.getInputStream();
        directory = Optional.ofNullable(directory).orElse("");
        String minFileName = directory + minFileName(multipartFile.getOriginalFilename());
        System.out.println(minFileName);
        System.out.println(multipartFile.getContentType());
        //上传文件到指定目录
        client.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(minFileName)
                .contentType(multipartFile.getContentType())
                .stream(inputStream, inputStream.available(), -1)
                .build());
        inputStream.close();
        // 返回生成文件名、访问路径
        return new MinIoUploadResDTO(minFileName, getObjectUrl(bucketName, minFileName, DEFAULT_EXPIRY));
    }

    public MinIoUploadResDTO uploadByBytes(byte[] bytes,String fileName, String bucketName, String directory) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        fileName =directory+"/"+fileName;
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectWriteResponse objectWriteResponse = client.putObject(PutObjectArgs.builder().bucket(bucketName)
                .object(fileName)
                .contentType("image/jpeg")
                .stream(byteArrayInputStream, byteArrayInputStream.available(), -1)
                .build());
        return new MinIoUploadResDTO(fileName,getObjectUrl(bucketName,fileName,DEFAULT_EXPIRY));
    }


    /**
     * @param response
     * @return java.lang.String
     * @Description 下载文件
     * @author exe.wangtaotao
     * @date 2020/10/21 15:18
     */
    public void download(HttpServletResponse response, String bucketName, String minFileName)  {
        InputStream fileInputStream = null;
        try {
            fileInputStream = client.getObject(GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(minFileName).build());
//            response.setHeader("Content-Disposition", "attachment;filename=" + minFileName);
//            response.setContentType("application/force-download");
            response.setContentType("image/jpeg");
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(fileInputStream, response.getOutputStream());
        } catch (ErrorResponseException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException | InsufficientDataException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 批量创建分片上传外链
     *
     * @param bucketName 存储桶名称
     * @param objectMD5  欲上传分片文件主文件的MD5
     * @param chunkCount 分片数量
     * @return uploadChunkUrls
     */
    public List<String> createUploadChunkUrlList(String bucketName, String objectMD5, Integer chunkCount) {
        if (null == bucketName) {
            bucketName = chunkBucKet;
        }
        if (null == objectMD5) {
            return null;
        }
        objectMD5 += "/";
        if (null == chunkCount || 0 == chunkCount) {
            return null;
        }
        List<String> urlList = new ArrayList<>(chunkCount);
        for (int i = 1; i <= chunkCount; i++) {
            String objectName = objectMD5 + i + ".chunk";
            urlList.add(createUploadUrl(bucketName, objectName, DEFAULT_EXPIRY));
        }
        return urlList;
    }

    /**
     * 创建指定序号的分片文件上传外链
     *
     * @param bucketName 存储桶名称
     * @param objectMD5  欲上传分片文件主文件的MD5
     * @param partNumber 分片序号
     * @return uploadChunkUrl
     */
    public String createUploadChunkUrl(String bucketName, String objectMD5, Integer partNumber) {
        if (null == bucketName) {
            bucketName = chunkBucKet;
        }
        if (null == objectMD5) {
            return null;
        }
        objectMD5 += "/" + partNumber + ".chunk";
        return createUploadUrl(bucketName, objectMD5, DEFAULT_EXPIRY);
    }


    /**
     * 获取分片文件名称列表
     *
     * @param bucketName 存储桶名称
     * @param ObjectMd5  对象Md5
     * @return objectChunkNames
     */
    public List<String> listChunkObjectNames(String bucketName, String ObjectMd5) {
        if (null == bucketName) {
            bucketName = chunkBucKet;
        }
        if (null == ObjectMd5) {
            return null;
        }
        return listObjectNames(bucketName, ObjectMd5, SORT);
    }

    /**
     * 获取分片名称地址HashMap key=分片序号 value=分片文件地址
     *
     * @param bucketName 存储桶名称
     * @param ObjectMd5  对象Md5
     * @return objectChunkNameMap
     */
    public Map<Integer, String> mapChunkObjectNames(String bucketName, String ObjectMd5) {
        if (null == bucketName) {
            bucketName = chunkBucKet;
        }
        if (null == ObjectMd5) {
            return null;
        }
        List<String> chunkPaths = listObjectNames(bucketName, ObjectMd5);
        if (null == chunkPaths || chunkPaths.size() == 0) {
            return null;
        }
        Map<Integer, String> chunkMap = new HashMap<>(chunkPaths.size());
        for (String chunkName : chunkPaths) {
            Integer partNumber = Integer.parseInt(chunkName.substring(chunkName.indexOf("/") + 1, chunkName.lastIndexOf(".")));
            chunkMap.put(partNumber, chunkName);
        }
        return chunkMap;
    }


    /**
     * 合并分片文件成对象文件
     *
     * @param chunkBucKetName   分片文件所在存储桶名称
     * @param composeBucketName 合并后的对象文件存储的存储桶名称
     * @param chunkNames        分片文件名称集合
     * @param objectName        合并后的对象文件名称
     * @return true/false
     */
    @SneakyThrows
    public boolean composeObject(String chunkBucKetName, String composeBucketName, List<String> chunkNames, String objectName, boolean isDeleteChunkObject) {
        if (null == chunkBucKetName) {
            chunkBucKetName = chunkBucKet;
        }
        List<ComposeSource> sourceObjectList = new ArrayList<>(chunkNames.size());
        for (String chunk : chunkNames) {
            sourceObjectList.add(
                    ComposeSource.builder()
                            .bucket(chunkBucKetName)
                            .object(chunk)
                            .build()
            );
        }
        client.composeObject(
                ComposeObjectArgs.builder()
                        .bucket(composeBucketName)
                        .object(objectName)
                        .sources(sourceObjectList)
                        .build()
        );
        if (isDeleteChunkObject) {
            removeObjects(chunkBucKetName, chunkNames);
        }
        return true;
    }

    /**
     * 合并分片文件成对象文件
     *
     * @param bucketName 存储桶名称
     * @param chunkNames 分片文件名称集合
     * @param objectName 合并后的对象文件名称
     * @return true/false
     */
    public boolean composeObject(String bucketName, List<String> chunkNames, String objectName) {
        return composeObject(chunkBucKet, bucketName, chunkNames, objectName, NOT_DELETE_CHUNK_OBJECT);
    }

    /**
     * 合并分片文件成对象文件
     *
     * @param bucketName 存储桶名称
     * @param chunkNames 分片文件名称集合
     * @param objectName 合并后的对象文件名称
     * @return true/false
     */
    public boolean composeObject(String bucketName, List<String> chunkNames, String objectName, boolean isDeleteChunkObject) {
        return composeObject(chunkBucKet, bucketName, chunkNames, objectName, isDeleteChunkObject);
    }

    /**
     * 合并分片文件,合并成功后删除分片文件
     *
     * @param bucketName 存储桶名称
     * @param chunkNames 分片文件名称集合
     * @param objectName 合并后的对象文件名称
     * @return true/false
     */
    public boolean composeObjectAndRemoveChunk(String bucketName, List<String> chunkNames, String objectName) {
        return composeObject(chunkBucKet, bucketName, chunkNames, objectName, DELETE_CHUNK_OBJECT);
    }


    /**
     * @param originalFileName
     * @return java.lang.String
     * @Description 生成上传文件名
     * @author exe.wangtaotao
     * @date 2020/10/21 15:07
     */
    private String minFileName(String originalFileName) {
        String suffix = originalFileName;
        if (originalFileName.contains(SEPARATOR_DOT)) {
            suffix = originalFileName.substring(originalFileName.lastIndexOf(SEPARATOR_DOT));
        }
        return UUID.randomUUID().toString().replace(SEPARATOR_ACROSS, SEPARATOR_STR).toUpperCase() + suffix;
    }


    /**
     * 将分钟数转换为秒数
     *
     * @param expiry 过期时间(分钟数)
     * @return expiry
     */
    private static int expiryHandle(Integer expiry) {
        expiry = expiry * 60;
        if (expiry > 604800) {
            return 604800;
        }
        return expiry;
    }

    static class Str2IntComparator implements Comparator<String> {
        private final boolean reverseOrder; // 是否倒序

        public Str2IntComparator(boolean reverseOrder) {
            this.reverseOrder = reverseOrder;
        }

        @Override
        public int compare(String arg0, String arg1) {
            Integer intArg0 = Integer.parseInt(arg0.substring(arg0.indexOf("/") + 1, arg0.lastIndexOf(".")));
            Integer intArg1 = Integer.parseInt(arg1.substring(arg1.indexOf("/") + 1, arg1.lastIndexOf(".")));
            if (reverseOrder) {
                return intArg1 - intArg0;
            } else {
                return intArg0 - intArg1;
            }
        }
    }

}

新建返回结果

代码语言:javascript
复制
package com.jd.minio;

import lombok.Data;

import java.io.Serializable;

@Data
public class MinIoUploadResDTO implements Serializable {

    private static final long serialVersionUID = 475040120689218785L;
    private String minFileName;
    private String minFileUrl;

    public MinIoUploadResDTO(String minFileName, String minFileUrl) {
        this.minFileName = minFileName;
        this.minFileUrl = minFileUrl;
    }
}

新建统一返回

代码语言:javascript
复制
package com.jd.minio;

import java.io.Serializable;

public class Result<T> implements Serializable {

    private static final long serialVersionUID = 6273326371984994386L;
    private Integer code;
    private String msg;
    private T data;

    private Result() {
        this.code = 200;
        this.msg = "OK";
    }

    private Result(T data) {
        this.code = 200;
        this.msg = "OK";
        this.setData(data);
    }

    private Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Result<T> setError(Integer code, String msg) {
        this.setCode(code);
        this.setMsg(msg);
        return this;
    }

    public boolean isSuccess() {
        return this.getCode().equals(200);
    }

    public static Result ok() {
        return new Result();
    }

    public static <T> Result ok(T data) {
        return new Result(data);
    }

    public static <T> Result ok(Integer code, String msg) {
        return new Result(code, msg);
    }

    public static <T> Result ok(Integer code, String msg, T data) {
        return new Result(code, msg, data);
    }

    public static <T> Result error() {
        return new Result(500, "failed");
    }

    public static <T> Result error(String msg) {
        return new Result(500, msg);
    }

    public static <T> Result error(Integer code, String msg) {
        return new Result(code, msg);
    }

    public static <T> Result error(Integer code, String msg, T data) {
        return new Result(code, msg, data);
    }

    public Integer getCode() {
        return this.code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return this.msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return this.data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

新建Controller

代码语言:javascript
复制
package com.jd.minio;

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/minio")
public class MinIoController {

    @Resource
    private MinIoUtils minIoUtils;

    // 存储桶名称
    private static final String MINIO_BUCKET = "image";

/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* private static final String base64 = "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";
*/



    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public Result upload(@RequestParam(value = "files") MultipartFile files){
        try {
            return Result.ok(minIoUtils.upload(files,MINIO_BUCKET,null));
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }
    @RequestMapping(value = "/file", method = RequestMethod.GET)
    public Result files(){
        try {
            BASE64Decoder base64Decoder = new BASE64Decoder();
            return Result.ok(minIoUtils.uploadByBytes(base64Decoder.decodeBuffer(base64),"20220804161251.jpeg",MINIO_BUCKET,"20220804"));
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @GetMapping("/download")
    public void download(@RequestParam("minFileName")String minFileName,HttpServletResponse response){
            minIoUtils.download(response,"image",minFileName);
    }
}

总结

有了这些, 大家就可以自己去玩了, 然后根据自己的业务改造

建议不要用MinIo自带的图片分享URL, 因为最大只支持7天, 我在网上找了一些方案, 基本都是直接通过文件夹路径访问, 但是只有单击可以, 我在集群上发现是不行的, 所以我是自己做了个接口直接返回图片流

扩展 返回图片流接口

代码语言:javascript
复制
public void download(HttpServletResponse response, String fileName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        try (
                InputStream inputStream = client.getObject(GetObjectArgs
                        .builder()
                        .bucket(bucket)
                        .object(fileName)
                        .build())) {
            response.setContentType("image/jpeg");
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(inputStream, response.getOutputStream());
        }
    }

通过传入文件名直接返回图片

okk

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 添加依赖
  • 新增yml配置
  • 新建配置类
  • 新建工具类
  • 新建返回结果
  • 新建统一返回
  • 新建Controller
  • 总结
  • 扩展 返回图片流接口
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档