minio的上传|minio多文件上传|minio修改端口号

简介

 

MiniO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。

 

正题

 

最近公司在做一个新项目,需要传输大量的图片或附件(下面都以图片叙述),如果按照传统的文件上传,有些繁琐了,作为一个合格的上进的程序猿,不应该技术停滞不前,要向前看嘛,所以研究了下较前沿的MiniO,再结合业务发现不错,所以在这里总结了下从安装到开发的过程。

 

                                                                              minio的上传|minio多文件上传|minio修改端口号_第1张图片

 

 

一 地址

 

自行去minio官网 https://min.io/ 这个不多说

 

                                                                               minio的上传|minio多文件上传|minio修改端口号_第2张图片

 

 

二 安装-启动minio服务

 

windows

安装完后会生成一下两个文件夹

 

minio的上传|minio多文件上传|minio修改端口号_第3张图片

 

点进去“server”文件夹,shift+右键,点击‘在此处打开命令窗口’

 

minio的上传|minio多文件上传|minio修改端口号_第4张图片


 

 

在终端输入:

minio.exe server D:\minio\file --address=0.0.0.0:9006

这里注意,minio默认启动语句为minio.exe server D:\minio\file,此时它会生成默认端口号:9000,我不想用9000端口,我要用9006,所以加后缀:--address=0.0.0.0:9006

 

执行完毕,如下图:

minio的上传|minio多文件上传|minio修改端口号_第5张图片

用户名和密码默认同为:minioadmin

如果想修改用户名或密码,可参考博文:

https://blog.csdn.net/weixin_44981485/article/details/106809902

ok,此刻你的minio已经启动完毕,浏览器输入:127.0.0.1:+端口号,可登入可视化界面,这个不做过多介绍了,登入进去就是你传输进来的图片,储存的文件位置就是上图的file文件夹。

 

linux

安装自行百度吧,过程差不多都一个样,本来也是不想介绍安装的。

 

                                                                                            minio的上传|minio多文件上传|minio修改端口号_第6张图片

 

 

三 开发

 

重头戏来了。

首先思路,前面说到不想每个业务表都搞个存储图片路径的字段,所以得建一个中间表,所以需要查询上传图片的业务,都根据上传时候的唯一标示到这个表里取一下,根据现在系统的业务,我的存储路径的表结构关键字段大体如下:

 

 

uuid_name:取服务器上的图片名称bucket_name:这个需要在开发时进行配置,说白了就是minio服务器存储图片文件的文件夹,这个后面开发会具体说到business_id:唯一标示id,我们的新产品数据库id使用的是uuid,比如说我想上传一个医生的头像,上传完成后,图片的url地址会存储在我的中间表url字段中,我就能通过医生id,来找到这个医生的头像。url:存储图片的可访问地址

在我项目的业务里,上传分为两种业务模式:

一:点击直接上传。也就是说要把图片传到我的新建的业务表中,同时也要上传到minio服务器。用户当场没有修改的机会,选中即上传。

二:间接上传。先把图片上传到minio服务器,我会返回图片的存储url给前端,这时候用户可以对图片做修改,修改后再返回给前端修改后的url,最后用户统一点提交按钮,完成业务表图片url的存储。

 

下面是开发实现时间:

我把minio给提供的api方法,做了一个封装,做成了公共调用模块,下面我会拆出来展示具体的minio的api的方法,如果需要看我封装的公共模块代码,业务模块就不给了,下面都有说,直接关注微信公众号:精神错乱猿,最下面也有公众号图片,公众号首页面回复:minio 就可以获取到了。

首先,先引入minio依赖,这没什么好说(我项目是springboot+maven,所以引入依赖就可以了,如果不是maven项目,那就去找下minio的jar吧)

 

依赖:

                    io.minio            minio            3.0.12        

 

minio服务器yml配置:

 

minio:// minio服务器地址+多口  url: http://127.0.0.0:9006  // 用户名密码  access-key: minioadmin  secret-key: minioadmin  // 配置这个是为了传的bucker和自己设定的一样,不然容易传错,再取的时候取不到,下面代码有说明  bucket-names:    - xx.xx.xxx   # 头衔图标

 

然后搞一下它的封装就好了:

 

private MinioClient client;

 

贴一下minio提供的方法

 

  /**   * 创建bucket   *   * @param bucketName bucket名称   */  @SneakyThrows  public void createBucket(String bucketName) {    if (!client.bucketExists(bucketName)) {      client.makeBucket(bucketName);    }  }

 

上面这块代码需要说明一下,minio要求在上传前需要在minio服务器创建bucket,说白了也就是文件夹,创建后会在服务器minio安装路径下创建bucket命名的文件夹。

 

  /**   * 获取全部bucket   */  @SneakyThrows  public List getAllBuckets() {    return client.listBuckets();  }  /**   * @param bucketName 获得单个bucket名称(做前后端上传的验证)   */  @SneakyThrows  public Optional getBucket(String bucketName) {    return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();  }    /**   * @param bucketName 删除bucket名称   */  @SneakyThrows  public void removeBucket(String bucketName) {    client.removeBucket(bucketName);  }  /**   * 根据文件前置查询文件   *   * @param bucketName bucket名称   * @param prefix     前缀   * @param recursive  是否递归查询   * @return MinioItem 列表   */  @SneakyThrows  public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {    List objectList = new ArrayList<>();    Iterable> objectsIterator = client        .listObjects(bucketName, prefix, recursive);    while (objectsIterator.iterator().hasNext()) {      objectList.add(new MinioItem(objectsIterator.iterator().next().get()));    }    return objectList;  }  /**   * 获取文件外链   *   * @param bucketName bucket名称   * @param objectName 文件名称   * @param expires    过期时间 <=7   * @return url   */  @SneakyThrows  public String getObjectURL(String bucketName, String objectName, Integer expires) {    return client.presignedGetObject(bucketName, objectName, expires);  }  /**   * 获取文件   *   * @param bucketName bucket名称   * @param objectName 文件名称   * @return 二进制流   */  @SneakyThrows  public InputStream getObject(String bucketName, String objectName) {    return client.getObject(bucketName, objectName);  }  /**   * 上传文件   *   * @param bucketName bucket名称   * @param objectName 文件名称   * @param stream     文件流   * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject   */  public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {    this.createBucket(bucketName);    client.putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");  }  /**   * 上传文件   *   * @param bucketName  bucket名称   * @param objectName  文件名称   * @param stream      文件流   * @param size        大小   * @param contextType 类型   * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject   */  public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {    client.putObject(bucketName, objectName, stream, size, contextType);  }  /**   * 获取文件信息   *   * @param bucketName bucket名称   * @param objectName 文件名称   * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject   */  public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {    return client.statObject(bucketName, objectName);  }  /**   * 删除文件   *   * @param bucketName bucket名称   * @param objectName 文件名称   * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject   */  public void removeObject(String bucketName, String objectName) throws Exception {    client.removeObject(bucketName, objectName);  }

 

正式代码实现,只列举上面提到的业务逻辑一的代码,业务逻辑二无非就是把下面代码做分离:

 

/** 这里需要前端传bucketName和businessId*///bucketName 文件夹名称// businessId 唯一业务id,区分是谁传的附件,上面逻辑有提到过//判断yml中是否有这个已写的BucketName,防止有业务场景需要前端传bucketName,导致名称写错,取得时候取不到if (!minioTemplate.getBucketNames().contains(bucketName)) {            return error("非法的bucketName!");        }        // 生成图片名        String fileName = IdWorker.getIdStr() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());        // 我的业务表        Attachment attachment = new Attachment();        try {            //创建一个MinIO的Java客户端            MinioClient minioClient = new MinioClient(MinioDeployConstant.ENDPOINT_TYPE, MinioDeployConstant.ACCESS_KEY_TYPE, MinioDeployConstant.SECRET_KEY_TYPE);            boolean isExist = minioClient.bucketExists(bucketName);            if (!isExist) {                /**第一次搞没写这块代码,导致bucker创建了,图片也上传上去了,但是只能下,却不能预览                需要登陆minio服务器后,把对应的bucker设置权限,这样太麻烦了,直接创建即设置权限 */                minioClient.makeBucket(bucketName);                minioClient.setBucketPolicy(bucketName, "*.*", PolicyType.READ_ONLY);            }            // 使用putObject上传一个文件到存储桶中            minioClient.putObject(bucketName, fileName, file.getInputStream(), file.getContentType());            // 获取图片存贮在服务器上的地址            String url = MinioDeployConstant.ENDPOINT_TYPE + "/" + bucketName + "/" + fileName;            // 上传            minioTemplate.putObject(bucketName, fileName, file.getInputStream());            // 业务数据保存            attachment.setUrl(url);            attachment.setBucketName(bucketName);            attachment.setUuidName(fileName);            attachment.setBusinessId(businessId);            infAttachmentService.save(attachment);

 

删除:

 

 minioTemplate.removeObject(bucketName, fileName);

 

多文件上传,在网上也没找到相关的demo,我自己采用流的方式:

 

 List fileList = ((MultipartHttpServletRequest) request).getFiles("file");            if (CollectionUtil.isEmpty(fileList)) {                return new R().error("上传的文件列表不能为空!");            }            if (fileList.size() > 9) {                return new R().error("上传失败,一次最多上传9个文件!");            }            String bucketName = request.getParameter("bucketName");            if (!minioTemplate.getBucketNames().contains(bucketName)) {                return new R().error("非法的bucketName");            }            Long businessId = Long.valueOf(request.getParameter("businessId"));            if (numberIsNullOrZero(businessId)) {                return new R().error("businessId is not find");            }            List attachmentList = new ArrayList<>();            for (MultipartFile file : fileList) {                String fileName = IdWorker.getIdStr() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());                Attachment attachment = new Attachment();                minioTemplate.putObject(bucketName, fileName, file.getInputStream());                attachment.setBucketName(bucketName);                attachment.setUuidName(fileName);                attachment.setBusinessId(businessId);                attachmentList.add(attachment);            }            return success("成功");

 

对于minio的更新操作,好像minio没有提供,还是我看api不够仔细。不过这都可以克服,无非就是用现有的方法先删除在上传就是了,业务数据也是如此,灵活变化。

对于minio的介绍就到这里了。

可以关注微信gongzhonghao:精神错乱猿,可以回复电影名,免费获取百度云链接电影。也会时常更新一些用到的技术。

下面是微信公众号图片:

minio的上传|minio多文件上传|minio修改端口号_第7张图片

 

 

你可能感兴趣的:(minio)