• 图片存储方案-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 }
  • 相关阅读:
    Excel设置下拉选项的方法
    Codeforces Round #218 (Div. 2) (线段树区间处理)
    手动配置S2SH三大框架报错(一)
    一种H.264高清视频的无参考视频质量评价算法(基于QP和跳过宏块数)
    UIWebView的使用
    AFNetworkIng的简单使用
    虚线边框的实现
    iOS实现简单时钟效果
    hdu 3966 Aragorn's Story
    Count on a tree
  • 原文地址:https://www.cnblogs.com/javashop-docs/p/14234787.html
Copyright © 2020-2023  润新知