圖片存儲方案-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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM