设计模式实战-Minio服务存储图片

2023-02-22  本文已影响0人  CoderInsight

1,Minio简介

提供对象存储的服务,适合存储非机构化的数据,例如一些图片、视频、日志文件等。

2,Minio服务部署

3,Java代码的基础操作

在基本操作的演示基础上,增加了模板类的封装;

(1),MinioConfiguration

import io.minio.MinioClient;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author wangyq
 * @date 2022/4/19 18:10
 * 将Minio的配置信息通过属性注入的方法交给springboot进行管理
 */
@Configuration
public class MinioConfiguration {

    @Value("${minio.endpoint:http://192.168.73.156:9000}")
    private String endPoint;
    @Value("${minio.accessKey:minioadmin}")
    private String accessKey;
    @Value("${minio.secretKey:minioadmin}")
    private String secretKey;
    @Value("${minio.bucketName:test}")
    public String bucketName;

    /**
     * @return 初始化minio操作的客户端
     * @throws InvalidPortException 端口异常
     * @throws InvalidEndpointException 连接地址异常
     * @author wangyq
     * @date 2023年2月22日 10:43:58
     */
    @Bean
    @ConditionalOnMissingBean({MinioClient.class})
    public MinioClient minioClient() throws InvalidPortException, InvalidEndpointException {
        return new MinioClient(this.endPoint, this.accessKey, this.secretKey);
    }

    /**
     * @author wangyq
     * @date 2022/4/19 18:11
     * @return  初始化模版方法
     */
    @Bean
    @ConditionalOnBean({MinioClient.class})
    @ConditionalOnMissingBean({MinioTemplate.class})
    public MinioTemplate minioTemplate(final MinioClient minioClient) {
        // 这里是直接new的对象,本质上是一样的
        return new MinioTemplate(minioClient, this.endPoint, this.bucketName);
    }
}

(2),MinioTemplate

import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.ServerSideEncryption;
import io.minio.messages.Bucket;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author wangyongqiang
 * Minio 的操作模板类
 */
public class MinioTemplate {
    /**minio连接地址*/
    private final String endPoint;

    /** 默认的桶名称*/
    private final String defaultBucket;

    /**minio客户端*/
    private final MinioClient client;

    public MinioTemplate(MinioClient client, String endPoint, String defaultBucket) {
        this.endPoint = endPoint;
        this.defaultBucket = defaultBucket;
        this.client = client;
    }

    public void makeBucket(String bucketName) throws Exception {
        if (!this.client.bucketExists(bucketName)) {
            this.client.makeBucket(bucketName);
            this.client.setBucketPolicy(bucketName, getPolicyType(bucketName, PolicyType.READ_WRITE));
        }
    }

    public Bucket getBucket(String bucketName) throws Throwable{
        try {
            Optional<Bucket> bucketOptional = this.client.listBuckets().stream().filter((bucket) -> {
                return bucket.name().equals(bucketName);
            }).findFirst();
            return (Bucket)bucketOptional.orElse((Bucket) null);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public List<Bucket> listBuckets() throws Exception{
        return this.client.listBuckets();
    }

    public void removeBucket(String bucketName) throws Exception{
        try {
            this.client.removeBucket(bucketName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public boolean bucketExists(String bucketName) throws Exception {
        try {
            return this.client.bucketExists(bucketName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void copyFile(String bucketName, String fileName, String destBucketName) throws Exception{
        try {
            this.client.copyObject(bucketName, fileName, destBucketName);
        } catch (Throwable var5) {
            throw var5;
        }
    }

    public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) throws Exception{
        try {
            this.client.copyObject(bucketName, fileName, destBucketName, destFileName);
        } catch (Throwable var6) {
            throw var6;
        }
    }

    public MinioFile statFile(String fileName) throws Exception{
        return this.statFile(this.defaultBucket, fileName);
    }

    /**
     * @author wangyq
     * @date 2022/4/19 15:38
     * @Description 判断对象是否存在
     */
    private MinioFile statFile(String bucketName, String fileName) throws Exception{
        ObjectStat stat = this.client.statObject(bucketName, fileName);

        MinioFile minioFile = new MinioFile();
        minioFile.setName(StringUtils.isBlank(stat.name()) ? fileName : stat.name());
        minioFile.setLink(this.fileLink(minioFile.getName()));
        minioFile.setHash(String.valueOf(stat.hashCode()));
        minioFile.setLength(stat.length());
        minioFile.setPutTime(stat.createdTime());
        minioFile.setContentType(stat.contentType());
        return minioFile;
    }

    public String filePath(String fileName) {
        return this.defaultBucket.concat("/").concat(fileName);
    }

    public String filePath(String bucketName, String fileName) {
        return bucketName.concat("/").concat(fileName);
    }

    private String fileLink(String fileName) {
        return this.endPoint.concat("/").concat(this.defaultBucket).concat("/").concat(fileName);
    }

    /**
     * @author wangyq
     * @date 2022/4/18 17:46
     * @Description 获取图片的完整访问路径
     */
    public String fileLink(String bucketName, String fileName) {
        return this.endPoint.concat("/").concat(bucketName).concat("/").concat(fileName);
    }

    public MinioFile putFile(MultipartFile file) throws Exception{
        try {
            return this.putFile(this.defaultBucket, file.getOriginalFilename(), file);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public MinioFile putFile(String fileName, MultipartFile file) throws Exception {
        try {
            return this.putFile(this.defaultBucket, fileName, file);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public MinioFile putFile(String bucketName, String fileName, MultipartFile file) throws Exception{
        return this.putFile(bucketName, fileName, file.getInputStream());
    }

    public MinioFile putFile(String fileName, InputStream stream) throws Exception {
        return this.putFile(this.defaultBucket, fileName, stream);
    }

    public MinioFile putFile(String bucketName, String fileName, InputStream stream) throws Exception{
        this.makeBucket(bucketName);
        this.client.putObject(bucketName, fileName, stream, (long)stream.available(), (Map)null, (ServerSideEncryption)null, "application/octet-stream");
        MinioFile file = new MinioFile();
        file.setName(fileName);
        file.setLink(this.fileLink(bucketName, fileName));
        file.setPutTime(new Date());
        return file;
    }

    public void removeFile(String fileName)  throws Exception{
        try {
            this.removeFile(this.defaultBucket, fileName);
        } catch (Throwable var3) {
            throw var3;
        }
    }

    public void removeFile(String bucketName, String fileName) throws Exception{
        this.client.removeObject(bucketName, fileName);
    }

    public void removeFiles(String bucketName, List<String> fileNames) {
        this.client.removeObjects(bucketName, fileNames);
    }

    /**
     * @author wangyq
     * @date 2022/4/18 16:01
     * @Description 经过测试可以实现图片文件的下载
     */
    public void downLoadFile(HttpServletResponse response, String bucketName, String fileName) throws Exception{
        InputStream inputStream = this.client.getObject(StringUtils.isBlank(bucketName) ? this.defaultBucket : bucketName, fileName);
        Throwable var5 = null;
        try {
            ServletOutputStream servletOutputStream = response.getOutputStream();
            Throwable var7 = null;
            try {
                response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8"));
                response.setHeader("content-type", "application/octet-stream");
                response.setContentType("application/force-download");
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "No-cache");
                response.setDateHeader("Expires", 0L);
                IOUtils.copy(inputStream, servletOutputStream);
            } catch (Throwable var32) {
                var7 = var32;
                throw var32;
            } finally {
                if (servletOutputStream != null) {
                    if (var7 != null) {
                        try {
                            servletOutputStream.close();
                        } catch (Throwable var31) {
                            var7.addSuppressed(var31);
                        }
                    } else {
                        servletOutputStream.close();
                    }
                }

            }
        } catch (Throwable var34) {
            var5 = var34;
            throw var34;
        } finally {
            if (inputStream != null) {
                if (var5 != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var30) {
                        var5.addSuppressed(var30);
                    }
                } else {
                    inputStream.close();
                }
            }
        }
    }

    public void downLoadFile(HttpServletResponse response, String fileName) throws Exception{
        try {
            this.downLoadFile(response, this.defaultBucket, fileName);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public void showImage(HttpServletResponse response, String bucketName, String fileName) throws Exception{
        InputStream inputStream = this.client.getObject(StringUtils.isBlank(bucketName) ? this.defaultBucket : bucketName, fileName);
        Throwable var5 = null;

        try {
            ServletOutputStream servletOutputStream = response.getOutputStream();
            Throwable var7 = null;

            try {
                String imageSuffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                response.setContentType("image/" + imageSuffix);
                //int len = false;
                byte[] buffer = new byte[10240];
                int len;
                while((len = inputStream.read(buffer)) != -1) {
                    servletOutputStream.write(buffer, 0, len);
                }
                servletOutputStream.flush();
            } catch (Throwable var34) {
                var7 = var34;
                throw var34;
            } finally {
                if (servletOutputStream != null) {
                    if (var7 != null) {
                        try {
                            servletOutputStream.close();
                        } catch (Throwable var33) {
                            var7.addSuppressed(var33);
                        }
                    } else {
                        servletOutputStream.close();
                    }
                }

            }
        } catch (Throwable var36) {
            var5 = var36;
            throw var36;
        } finally {
            if (inputStream != null) {
                if (var5 != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var32) {
                        var5.addSuppressed(var32);
                    }
                } else {
                    inputStream.close();
                }
            }
        }
    }

    public void showImage(HttpServletResponse response, String fileName)  throws Exception{
        try {
            this.showImage(response, this.defaultBucket, fileName);
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public String getUrl(String bucketName, String fileName)  throws Exception{
        try {
            String url = this.client.getObjectUrl(StringUtils.isBlank(bucketName) ? this.defaultBucket : bucketName, fileName);
            return url;
        } catch (Throwable var4) {
            throw var4;
        }
    }

    public static String getPolicyType(String bucketName, PolicyType policyType) {
        StringBuilder builder = new StringBuilder();
        builder.append("{\n");
        builder.append("    \"Statement\": [\n");
        builder.append("        {\n");
        builder.append("            \"Action\": [\n");
        switch(policyType) {
        case WRITE:
            builder.append("                \"s3:GetBucketLocation\",\n");
            builder.append("                \"s3:ListBucketMultipartUploads\"\n");
            break;
        case READ_WRITE:
            builder.append("                \"s3:GetBucketLocation\",\n");
            builder.append("                \"s3:ListBucket\",\n");
            builder.append("                \"s3:ListBucketMultipartUploads\"\n");
            break;
        default:
            builder.append("                \"s3:GetBucketLocation\"\n");
        }

        builder.append("            ],\n");
        builder.append("            \"Effect\": \"Allow\",\n");
        if (PolicyType.READ.equals(policyType)) {
            builder.append("        {\n");
            builder.append("            \"Action\": [\n");
            builder.append("                \"s3:ListBucket\"\n");
            builder.append("            ],\n");
            builder.append("            \"Effect\": \"Deny\",\n");
        }

        builder.append("            \"Principal\": \"*\",\n");
        builder.append("            \"Resource\": \"arn:aws:s3:::");
        builder.append(bucketName);
        builder.append("\"\n");
        builder.append("        },\n");
        builder.append("        {\n");
        builder.append("            \"Action\": ");
        switch(policyType) {
        case WRITE:
            builder.append("[\n");
            builder.append("                \"s3:AbortMultipartUpload\",\n");
            builder.append("                \"s3:DeleteObject\",\n");
            builder.append("                \"s3:ListMultipartUploadParts\",\n");
            builder.append("                \"s3:PutObject\"\n");
            builder.append("            ],\n");
            break;
        case READ_WRITE:
            builder.append("[\n");
            builder.append("                \"s3:AbortMultipartUpload\",\n");
            builder.append("                \"s3:DeleteObject\",\n");
            builder.append("                \"s3:GetObject\",\n");
            builder.append("                \"s3:ListMultipartUploadParts\",\n");
            builder.append("                \"s3:PutObject\"\n");
            builder.append("            ],\n");
            break;
        default:
            builder.append("\"s3:GetObject\",\n");
        }

        builder.append("            \"Effect\": \"Allow\",\n");
        builder.append("            \"Principal\": \"*\",\n");
        builder.append("            \"Resource\": \"arn:aws:s3:::");
        builder.append(bucketName);
        builder.append("/*\"\n");
        builder.append("        }\n");
        builder.append("    ],\n");
        builder.append("    \"Version\": \"2012-10-17\"\n");
        builder.append("}\n");
        return builder.toString();
    }
}

(3),MinioFile

import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;

/**
 * 控制返回的实体类信息
 * @author wangyq
 * @date 2022/4/19 10:55
 */
public class MinioFile {
    private String link;
    private String name;
    public String hash;
    private long length;
    @JsonFormat(
        pattern = "yyyy-MM-dd HH:mm:ss",
        timezone = "GMT+8"
    )
    private Date putTime;
    private String contentType;

    public MinioFile() {
    }

    public String getLink() {
        return this.link;
    }

    public String getName() {
        return this.name;
    }

    public String getHash() {
        return this.hash;
    }

    public long getLength() {
        return this.length;
    }

    public Date getPutTime() {
        return this.putTime;
    }

    public String getContentType() {
        return this.contentType;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setHash(String hash) {
        this.hash = hash;
    }

    public void setLength(long length) {
        this.length = length;
    }

    public void setPutTime(Date putTime) {
        this.putTime = putTime;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof MinioFile)) {
            return false;
        } else {
            MinioFile other = (MinioFile)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label75: {
                    Object thisLink = this.getLink();
                    Object otherLink = other.getLink();
                    if (thisLink == null) {
                        if (otherLink == null) {
                            break label75;
                        }
                    } else if (thisLink.equals(otherLink)) {
                        break label75;
                    }
                    return false;
                }
                Object thisName = this.getName();
                Object otherName = other.getName();
                if (thisName == null) {
                    if (otherName != null) {
                        return false;
                    }
                } else if (!thisName.equals(otherName)) {
                    return false;
                }
                Object thisHash = this.getHash();
                Object otherHash = other.getHash();
                if (thisHash == null) {
                    if (otherHash != null) {
                        return false;
                    }
                } else if (!thisHash.equals(otherHash)) {
                    return false;
                }
                if (this.getLength() != other.getLength()) {
                    return false;
                } else {
                    Object thisPutTime = this.getPutTime();
                    Object otherPutTime = other.getPutTime();
                    if (thisPutTime == null) {
                        if (otherPutTime != null) {
                            return false;
                        }
                    } else if (!thisPutTime.equals(otherPutTime)) {
                        return false;
                    }
                    Object thisContentType = this.getContentType();
                    Object otherContentType = other.getContentType();
                    if (thisContentType == null) {
                        return otherContentType == null;
                    } else {
                        return thisContentType.equals(otherContentType);
                    }
                }
            }
        }
    }

    private boolean canEqual(Object other) {
        return other instanceof MinioFile;
    }

    @Override
    public int hashCode() {
        int result = 17;
        // 这里的hashCode的顺序是和equals方法里的顺序保持一致的
        // String link;
        Object link = this.getLink();
        result = result * 31 + (link == null ? 43 : link.hashCode());
        // String name;
        Object name = this.getName();
        result = result * 31 + (name == null ? 43 : name.hashCode());
        // String hash;
        Object hash = this.getHash();
        result = result * 31 + (hash == null ? 43 : hash.hashCode());
        // long length;
        long length = this.getLength();
        result = result * 31 + (int)(length >>> 32 ^ length);
        // Date putTime;
        Object putTime = this.getPutTime();
        result = result * 31 + (putTime == null ? 43 : putTime.hashCode());
        // String contentType;
        Object contentType = this.getContentType();
        result = result * 31 + (contentType == null ? 43 : contentType.hashCode());
        return result;
    }

    @Override
    public String toString() {
        return "MinioFile(link=" + this.getLink() + ", name=" + this.getName() + ", hash=" + this.getHash() + ", length=" + this.getLength() + ", putTime=" + this.getPutTime() + ", contentType=" + this.getContentType() + ")";
    }
}

(4),PolicyType

/**
 * 文件上传权限控制枚举类
 * @author wangyongqiang
 */
public enum PolicyType {
    /**
     * 文件上传的权限
     * */
    READ("read", "只读"),
    WRITE("write", "只写"),
    READ_WRITE("read_write", "读写");

    private final String type;
    private final String policy;

    public String getType() {
        return this.type;
    }

    public String getPolicy() {
        return this.policy;
    }

    PolicyType(String type, String policy) {
        this.type = type;
        this.policy = policy;
    }
}

(5),基础API简介

只列举个别api其他重载方法可以查看模版方法

上一篇 下一篇

猜你喜欢

热点阅读