图片存储方案-MinIo

背景

文件存储是各个系统中必不可少的一部分,比如在电商系统中的商品图片存储,基本需求是大容量存储、快速访问、缩略图自动生成,现在有很多云服务如阿里的oss可以满足,在这里我们分享基于minio自建图片存储方案

minIO简介:

Minio 是个基于 Golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。

 

部署:

创建文件

1 mkdir -p /opt/data/minIO/datadocker 

启动命令

1 docker run -d -p 9000:9000 
2   --name minio 
3   -v /opt/data/minIO/data:/data 
4   -e "MINIO_ACCESS_KEY=root" 
5   -e "MINIO_SECRET_KEY=root1234" 
6   minio/minio server /data
1 用户名:MINIO_ACCESS_KEY (用户名最低3位) 
2 密码: MINIO_SECRET_KEY (密码最低8位)

详细见 : min.io官网

代码展示:

javashop商城为了更好的对接更多的平台,所以文件上传功能实现了插件化,降低代码耦合,也方便二次开发,

文件上传接口类:

 1 /**
 2  * 存储方案参数接口
 3  */
 4 public interface Uploader {
 5 
 6     /**
 7      * 配置各个存储方案的参数
 8      * @return 参数列表
 9      */
10     List<ConfigItem> definitionConfigItem();
11 
12     /**
13      * 上传文件
14      * @param input  上传对象
15      * @param scene  业务场景
16      * @param config 配置信息
17      * @return
18      */
19     FileVO upload(FileDTO input, String scene, Map config);
20 
21     /**
22      * 删除文件
23      * @param filePath 文件地址
24      * @param config   配置信息
25      */
26     void deleteFile(String filePath, Map config);
27 
28     /**
29      * 获取插件ID
30      * @return 插件beanId
31      */
32     String getPluginId();
33 
34     /**
35      * 生成缩略图路径
36      * @param url    原图片全路径
37      * @param width  需要生成图片尺寸的宽
38      * @param height 需要生成图片尺寸的高
39      * @return 生成的缩略图路径
40      */
41     String getThumbnailUrl(String url, Integer width, Integer height);
42 
43     /**
44      * 存储方案是否开启
45      * @return 0 不开启  1 开启
46      */
47     Integer getIsOpen();
48 
49     /**
50      * 获取插件名称
51      * @return 插件名称
52      */
53     String getPluginName();
54 }

minIO的插件类

javashop商城 实现 minIO的插件类:

  1 @Component
  2 public class MinIOPlugin implements Uploader {
  3     /**
  4      * 获取配置参数
  5      */
  6     @Override
  7     public List<ConfigItem> definitionConfigItem() {
  8         List<ConfigItem> list = new ArrayList();
  9 
 10         ConfigItem endpoint = new ConfigItem();
 11         endpoint.setType("text");
 12         endpoint.setName("endpoint");
 13         endpoint.setText("minIO服务地址");
 14 
 15         ConfigItem accessKey = new ConfigItem();
 16         accessKey.setType("text");
 17         accessKey.setName("accessKey");
 18         accessKey.setText("用户名");
 19 
 20         ConfigItem SecretKey = new ConfigItem();
 21         SecretKey.setType("text");
 22         SecretKey.setName("secretKey");
 23         SecretKey.setText("密钥");
 24 
 25         list.add(serviceUrl);
 26         list.add(accessKey);
 27         list.add(SecretKey);
 28 
 29         return list;
 30     }
 31 
 32     /**
 33      * 获取连接
 34      */
 35     public MinioClient getClient(Map config, String scene) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException, RegionConflictException, InvalidObjectPrefixException {
 36         String accessKeyId = StringUtil.toString(config.get("accessKey"));
 37         String accessKeySecret = StringUtil.toString(config.get("secretKey"));
 38         String endpoint = StringUtil.toString(config.get("endpoint"));
 39         //进行连接
 40         MinioClient minioClient = new MinioClient(endpoint, accessKeyId, accessKeySecret);
 41         //如果桶为空
 42         if (!minioClient.bucketExists(scene)) {
 43             //创建桶
 44             minioClient.makeBucket(scene);
 45             //创建桶的文件为全部可读
 46             minioClient.setBucketPolicy(scene, "*", PolicyType.READ_ONLY);
 47         }
 48         return minioClient;
 49     }
 50 
 51     @Override
 52     public FileVO upload(FileDTO input, String scene, Map config) {
 53         // 获取文件后缀
 54         String ext = input.getExt();
 55         //生成随机图片名
 56         String picName = UUID.randomUUID().toString().toUpperCase().replace("-", "") + "." + ext;
 57 
 58         MinioClient minioClient = null;
 59         try {
 60             //获取连接
 61             minioClient = this.getClient(config, scene);
 62             //文件上传
 63             minioClient.putObject(scene, picName, input.getStream(), input.getStream().available(), "image/" + ext);
 64 
 65         } catch (Exception e) {
 66             throw new ServiceException(SystemErrorCode.E802.code(), "上传图片失败");
 67         }
 68         String serviceUrl = StringUtil.toString(config.get("serviceUrl"));
 69         FileVO file = new FileVO();
 70         file.setName(picName);
 71         file.setExt(ext);
 72         file.setUrl(serviceUrl + "/" + scene + "/" + picName);
 73         return file;
 74     }
 75 
 76     @Override
 77     public void deleteFile(String filePath, Map config) {
 78         MinioClient minioClient = null;
 79         String[] split = filePath.split("/");
 80         String bucketName = "";
 81         String objectName = "";
 82         for (int i = 0; i < split.length; i++) {
 83             if (i == 3) {
 84                 bucketName = split[i];
 85             }
 86         }
 87         if (bucketName.length() > 3) {
 88             objectName = filePath.substring(filePath.indexOf(bucketName) + bucketName.length() + 1);
 89         } else {
 90             throw new ServiceException(SystemErrorCode.E803.code(), "删除失败,无法解析路径");
 91         }
 92         try {
 93             minioClient = this.getClient(config, bucketName);
 94             minioClient.removeObject(bucketName, objectName);
 95         } catch (Exception e) {
 96             throw new ServiceException(SystemErrorCode.E903.code(),"删除图片失败");
 97         }
 98 
 99     }
100 
101     @Override
102     public String getPluginId() {
103         return "minIOPlugin";
104     }
105 
106     @Override
107     public String getThumbnailUrl(String url, Integer width, Integer height) {
108         // 缩略图全路径
109         String thumbnailPah = url + "_" + width + "x" + height;
110         // 返回缩略图全路径
111         return thumbnailPah;
112     }
113 
114     @Override
115     public Integer getIsOpen() {
116         return 0;
117     }
118 
119     @Override
120     public String getPluginName() {
121         return "MinIO存储";
122     }
123 }

文件上传入口方法:

 1  /**
 2      * 文件上传<br>
 3      * 接受POST请求<br>
 4      * 同时支持多择文件上传和截图上传
 5      * @param upfile 文件流
 6      * @return
 7      * @throws JSONException
 8      * @throws IOException
 9      */
10     @PostMapping(value = "/")
11     @ApiOperation(value = "ueditor文件/图片上传")
12     public Map upload( MultipartFile upfile) throws JSONException, IOException {
13         Map result = new HashMap(16);
14         if (upfile != null && upfile.getOriginalFilename() != null) {
15             //文件类型
16             String contentType= upfile.getContentType();
17             //获取文件名称后缀
18             String ext = contentType.substring(contentType.lastIndexOf("/") + 1, contentType.length());
19 
20             if(!FileUtil.isAllowUpImg(ext)){
21                 result.put("state","不允许上传的文件格式,请上传gif,jpg,png,jpeg,mp4格式文件。");
22                 return  result;
23             }
24             FileDTO input  = new FileDTO();
25             input.setName(upfile.getOriginalFilename());
26             input.setStream(upfile.getInputStream());
27             input.setExt(ext);
28             FileVO file  = this.fileManager.upload(input, "ueditor");
29             String url  = file.getUrl();
30             String title = file.getName();
31             String original = file.getName();
32             result.put("state","SUCCESS");
33             result.put("url", url);
34             result.put("title", title);
35             result.put("name", title);
36             result.put("original", original);
37             result.put("type","."+file.getExt());
38             return  result;
39         }else{
40             result.put("state","没有读取要上传的文件");
41             return  result;
42         }
43     }
44 }
原文地址:https://www.cnblogs.com/javashop-docs/p/14234787.html