minio使用


简单描述

minIO是一个分布式的对象存储系统,它提供了与Amazon Web Service S3兼容的API,并支持所有核心S3功能。
minIO可以部署在裸机环境,即X86等低成本机器等。

单机部署

安装minio服务

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/

启动minio

#在家目录创建文件存储路径

mkdir ~/minio

#使用默认端口启动minio

minio server ~/minio

#设置控制台端口启动minio

minio server ~/minio --console-address :9090

#修改minio的初始账号和密码,并设置控制台端口启动minio

MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server  ~/minio --console-address :9090

#修改minio的初始账号和密码

export MINIO_ROOT_USER=minio
export MINIO_ROOT_PASSWORD=12345678

备注:密码至少八位

浏览器访问minio服务

http://ip:9090

minio部署后台运行

使用systemd service功能管理minio服务的启动和停止等。

创建配置文件
mkdir -p /opt/minio/config
touch minio.config
创建minio.conf

在/opt/minio/conf目录下新建minion.conf,输入以下内容:

MINIO_VOLUMES="/opt/minio/data"
MINIO_OPTS="--console-address :9090 --address :9000"
MINIO_ROOT_USER="minio"
MINIO_ROOT_PASSWORD="12345678"
创建minio.service

在/etc/systemd/system目录下新建一个minio.service,输入内容:

[Unit]
Description=minio
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/opt/minio/minio

[Service]
#User and group
User=root
Group=root

#创建的配置文件 minio.conf
EnvironmentFile=/opt/minio/config/minio.conf
ExecStart=/opt/minio/minio server $MINIO_OPTS $MINIO_VOLUMES
#Let systemd restart this service always
Restart=always

#Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536

#Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no
[Install]
WantedBy=multi-user.target

修改系统服务

(1)将服务设置为每次开机启动

systemctl enable minio.service

(2)重新加载服务的配置文件
如果新安装的服务归属于 systemctl 管理,要使新服务的配置文件生效,需重新加载。

systemctl deamon-reload

(3)启动服务

systemctl start minio

(4)停止服务

systemctl stop minio

(5)重启服务

systemctl restart minio

(6)查看服务状态

systemctl status minio

springboot整合minio

引入依赖

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.3</version>
</dependency>

springboot minio client配置

package com.ym.minio.config;

import com.ym.minio.base.config.MinioProperty;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {
	@Autowired
	private MinioProperty minioProperties;

	@Bean
	public MinioClient minioClient(){
		MinioClient minioClient =
				MinioClient.builder()
						.endpoint(minioProperties.getUrl())
						.credentials(minioProperties.getAccessKey(),
								minioProperties.getSecretKey())
						.build();
		return minioClient;
	}

}
## springboot minio属性配置
minio:
  bucketName: bucket001
  expiry: 24
  url: http://192.168.117.129:9000
  accesskey: minio
  secretKey: 12345678

java api查看

官网java api

postman请求接口

postman测试接口列表

MinioService.java

package com.ym.minio.service;

import com.ym.minio.base.response.BaseResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;


import java.util.List;
import java.util.Map;

public interface MinioService {
	public static final String KEY_FILENAME = "fileName";
	public static final String KEY_PRESIGNEDOBJECTURL = "presignedObjectUrl";

	public static final String KEY_BUCKETNAME = "bucketName";
	public static final String KEY_FILEINFO = "fileInfo";
	public static final String KEY_FILELIST = "fileList";

	public static final String FILESIZE_0B = "0B";

	public BaseResponse<Map<String, Object>> createBucket(String bucketName);

	public BaseResponse<Map<String, Object>> delBucket(String bucketName);

	public BaseResponse<List<Map<String, Object>>> getBucketList();

	public BaseResponse<Map<String, Object>> getPresignedObjectUrl(String bucket, String fileName);
	public BaseResponse<String> delete(String bucket, String fileName);

	public void download(HttpServletResponse response, String bucket, String dir, String fileName);

	public ResponseEntity<byte[]> downloadByte(String bucket, String fileName);

	public BaseResponse<Map<String, Object>> upload(String bucket, String dir, MultipartFile[] file);

	public BaseResponse<Map<String, List<Object>>> list(String bucket);

	public BaseResponse<String> downloadObject(String bucket, String objName, String fileName);
}

MinioServiceImpl.java

package com.ym.minio.service.impl;


import com.alibaba.fastjson.JSON;
import com.ym.minio.base.config.MinioProperty;
import com.ym.minio.base.constant.CommonErrorCode;
import com.ym.minio.base.constant.MinioBucketHandle;
import com.ym.minio.base.response.BaseResponse;
import com.ym.minio.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class MinioServiceImpl implements MinioService {
	@Autowired
	private MinioClient minioClient;
	@Autowired
	private MinioProperty minioProperty;

	@Autowired
	private MinioUtil minioUtil;

	public BaseResponse<Map<String, Object>> createBucket(String bucketName) {
		int state = minioUtil.makeBucket(bucketName);

		if (state == MinioBucketHandle.BUCKETCREATED_SUCCESS.getState()) {
			return BaseResponse.SUCCESSFUL();
		} else {
			return BaseResponse.FAILED();
		}
	}

	public BaseResponse<Map<String, Object>> delBucket(String bucketName) {
		int state = minioUtil.removeBucket(bucketName);

		if (state == MinioBucketHandle.BUCKETDEL_SUCCESS.getState()) {
			return BaseResponse.SUCCESSFUL();
		} else {
			return BaseResponse.FAILED();
		}
	}

	public BaseResponse<List<Map<String, Object>>> getBucketList() {
		try {
			List<Bucket> buckets = minioClient.listBuckets();
			List<Map<String, Object>> result = new ArrayList<>();

			if (null != buckets && buckets.size() > 0) {
				for (Bucket bucket : buckets) {
					Map<String, Object> map = new HashMap<>();
					map.put("name", bucket.name());
					result.add(map);
				}
				return BaseResponse.success(result);
			} else {
				return BaseResponse.success(result);
			}
		} catch (Exception e) {
			log.error("getBucketList,e:{}", e);
			return BaseResponse.FAILED();
		}
	}


	public BaseResponse<Map<String, Object>> getPresignedObjectUrl(String bucket, String fileName) {
		try {
			String presignedObjectUrl = minioUtil.getPresignedObjectUrl(bucket, fileName, minioProperty.getExpiry());
			Map<String, Object> result = new HashMap<>();
			result.put(MinioService.KEY_PRESIGNEDOBJECTURL, presignedObjectUrl);

			return BaseResponse.success(result);
		} catch (Exception e) {
			log.error("getPresignedObjectUrl,e:{}",e);
			return BaseResponse.FAILED();
		}
	}

	public BaseResponse<String> delete(String bucket, String fileName) {
		try {
			GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucket).object(fileName).build();
			GetObjectResponse object = minioClient.getObject(getObjectArgs);
			if (null == object) {
				log.error("delete,fileName not exist");
				return BaseResponse.FAILED();
			} else {
				minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(fileName).build());
			}
		} catch (Exception e) {
			log.error("delete,e:{}", e);
			return BaseResponse.FAILED();
		}
		return BaseResponse.SUCCESSFUL();
	}

	@Override
	public void download(HttpServletResponse response, String bucket, String dir, String fileName) {
		String path = "";
		if (!StringUtils.isEmpty(dir)) {
			path = dir;
		}

		InputStream in = null;

		try {
			// 获取对象信息
			StatObjectResponse stat = minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(fileName).build());
			response.setContentType(stat.contentType());
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
			//文件下载
			in = minioClient.getObject(
					GetObjectArgs.builder()
							.bucket(bucket)
							.object(path + fileName)
							.build());
			IOUtils.copy(in, response.getOutputStream());
		} catch (Exception e) {
			log.error("download,e1:{}", e.getMessage());
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					log.error("download,e2:{}", e);
				}
			}
		}
	}

	@Override
	public ResponseEntity<byte[]> downloadByte(String bucket, String fileName) {
		InputStream in = null;

		try {
			//文件下载
			in = minioClient.getObject(
					GetObjectArgs.builder()
							.bucket(bucket)
							.object(fileName)
							.build());
			byte[] bytes = IOUtils.toByteArray(in);
			return new ResponseEntity(bytes, null, HttpStatus.OK);
		} catch (Exception e) {
			log.error("download,e1:{}", e.getMessage());
			return new ResponseEntity(null, null, HttpStatus.OK);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					log.error("download,e2:{}", e);
				}
			}
		}
	}

	public BaseResponse<Map<String, Object>> upload(String bucket, String dir, MultipartFile[] file) {
		if (file == null || file.length == 0) {
			return BaseResponse.error(CommonErrorCode.FAILED, "上传文件为空", null);
		}

		try {
			List<Map<String, Object>> stringList = minioUtil.putObject(dir, file, bucket);
			Map<String, Object> data = new HashMap<String, Object>();
			data.put(MinioService.KEY_BUCKETNAME, bucket);
			data.put(MinioService.KEY_FILELIST, stringList);

			return BaseResponse.success(data);
		} catch (Exception e) {
			log.error("upload,e:{}", e);
		}

		return BaseResponse.FAILED();
	}

	public BaseResponse<Map<String, List<Object>>> list1(String buckent) {
		try {
			minioUtil.makeBucket(minioProperty.getBucketName());

			List<Object> items = new ArrayList<>();
			String format = "{'fileName':'%s','fileSize':'%s', 'uploadedTime':'%s', 'resignedObjectUrl':'%s'}";

			getList(format, items, buckent, "");

			Map<String, List<Object>> fileList = new HashMap<>();
			fileList.put(MinioService.KEY_FILELIST, items);
			return BaseResponse.success(fileList);
		} catch (Exception e) {
			log.error("list,e:{}", e);
		}
		return BaseResponse.error(CommonErrorCode.FAILED, "获取列表失败", null);
	}

	public BaseResponse<Map<String, List<Object>>> list(String bucket) {
		try {
			minioUtil.makeBucket(bucket);

			Iterable<Result<Item>> myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).build());
			Iterator<Result<Item>> iterator = myObjects.iterator();
			List<Object> items = new ArrayList<>();
			String format = "{'fileName':'%s','fileSize':'%s', 'uploadedTime':'%s', 'resignedObjectUrl':'%s'}";
			while (iterator.hasNext()) {
				Item item = iterator.next().get();
				DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"));
				String resignedObjectUrl = minioClient.getPresignedObjectUrl(
						GetPresignedObjectUrlArgs
								.builder()
								.method(Method.GET)
								.bucket(bucket)
								.object(item.objectName())
								.expiry(minioProperty.getExpiry(), TimeUnit.HOURS)
								.build());

					String strTime = "";
					if (!item.isDir()) {
						strTime = item.lastModified().format(formatter);
					}

					items.add(JSON.parse(String.format(
							format,
							item.objectName(),
							minioUtil.formatFileSize(item.size()),
							strTime,
							resignedObjectUrl)));
			}

			Map<String, List<Object>> fileList = new HashMap<>();
			fileList.put(MinioService.KEY_FILELIST, items);

			return BaseResponse.success(fileList);
		} catch (Exception e) {
			log.error("list,e:{}", e);
		}
		return BaseResponse.error(CommonErrorCode.FAILED, "获取列表失败", null);
	}

	public BaseResponse<String> downloadObject(String bucket, String objectName, String fileName) {
		try {
			log.info("objectName:{},fileName:{}",objectName, fileName);
			minioClient.downloadObject(DownloadObjectArgs.builder().bucket(bucket).object(objectName).filename(fileName).build());
			return BaseResponse.success(fileName);
		} catch (Exception e) {
			log.error("downloadObject,e:{}", e);
			return BaseResponse.FAILED();
		}
	}

	private void getList(String format, List<Object> items, String bucketName, String minioPath) throws Exception {
		Iterable<Result<Item>> myObjects;

		if (minioPath.equals("")) {
			myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
		} else {
			myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(minioPath).build());
		}

		Iterator<Result<Item>> iterator = myObjects.iterator();

		while (iterator.hasNext()) {
			Item item = iterator.next().get();
			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("Asia/Shanghai"));
			String resignedObjectUrl = minioClient.getPresignedObjectUrl(
					GetPresignedObjectUrlArgs
							.builder()
							.method(Method.GET)
							.bucket(bucketName)
							.object(item.objectName())
							.expiry(minioProperty.getExpiry(), TimeUnit.HOURS)
							.build());
			if (!item.isDir()) {
				items.add(JSON.parse(String.format(
						format,
						item.objectName(),
						minioUtil.formatFileSize(item.size()),
						item.lastModified() != null ? item.lastModified().format(formatter) : "",
						resignedObjectUrl)));
			} else {
				getList(format, items, bucketName, minioPath + File.separator + item.objectName());
			}
		}
	}
}

MinioUtil.java

package com.ym.minio.service.impl;


import com.ym.minio.base.config.MinioProperty;
import com.ym.minio.base.constant.MinioBucketHandle;
import com.ym.minio.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class MinioUtil {
	@Autowired
	private MinioClient minioClient;

	@Autowired
	private MinioProperty minioProperty;

	/**
	 * @param bucketName 存储桶名称
	 */
	public int makeBucket(String bucketName) {
		try {
			//判断存储桶存不存在
			BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
			boolean bucketExisted = minioClient.bucketExists(bucketExistsArgs);
			//创建桶
			if (!bucketExisted) {
				MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
				minioClient.makeBucket(makeBucketArgs);
				log.debug("bucketName:{},created", bucketName);
				return MinioBucketHandle.BUCKETCREATED_SUCCESS.getState();
			} else {
				log.debug("bucketName:{},existed", bucketName);
				return MinioBucketHandle.BUCKETCREATED_FAILURE.getState();
			}
		} catch (Exception e) {
			log.error("makeBucket,e:{}", e);
			return MinioBucketHandle.BUCKETCREATED_EXCEPTION.getState();
		}
	}


	/**
	 *
	 * @param bucketName 存储桶名称
	 * @throws Exception
	 */
	public int removeBucket(String bucketName) {
		try {
			BucketExistsArgs exist = BucketExistsArgs.builder().bucket(bucketName).build();
			boolean result = minioClient.bucketExists(exist);
			if (!result) {
				return MinioBucketHandle.BUCKETDEL_FAILURE.getState();
			}

			minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
			log.debug("removeBucket success");
			return MinioBucketHandle.BUCKETDEL_SUCCESS.getState();
		} catch (Exception e) {
			log.error("removeBucket,e:{}", e);
			return MinioBucketHandle.BUCKETDEL_EXCEPTION.getState();
		}
	}

	/**
	 * @param bucketName 存储桶名称。
	 * @param objectName 存储桶里的对象名称
	 * @return
	 * @throws Exception
	 */
	public StatObjectResponse statObject(String bucketName,String objectName) {
		try {
			StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
			return statObjectResponse;
		} catch (Exception e) {
			log.error("statObject, e:{}", e);
			return null;
		}
	}

	/**
	 * 上传文件
	 * @param files 文件
	 * @param bucketName 存储桶名称
	 */
	public List<Map<String, Object>> putObject(String dir, MultipartFile[] files, String bucketName) {
		String path = "";
		if (!StringUtils.isEmpty(dir)) {
			path = dir;
		}

		List<Map<String, Object>> ret = new ArrayList<>();

		for (MultipartFile multipartFile : files) {
			//获取文件名
			String orgfileName = multipartFile.getOriginalFilename();
			Map<String, Object> m = new HashMap<>();
			m.put(MinioService.KEY_FILENAME, orgfileName);
			try {
				//文件上传
				InputStream in = multipartFile.getInputStream();
				minioClient.putObject(
						PutObjectArgs.
								builder().
								bucket(bucketName).
								object(path + orgfileName)
								.stream(in, multipartFile.getSize(), -1)
								.contentType(multipartFile.getContentType())
								.build());

				String presignedObjectUrl = minioClient.getPresignedObjectUrl(
						GetPresignedObjectUrlArgs
								.builder()
								.method(Method.GET)
								.bucket(bucketName)
								.object(path + orgfileName)
								.expiry(minioProperty.getExpiry(), TimeUnit.HOURS)
								.build());
				m.put(MinioService.KEY_PRESIGNEDOBJECTURL, presignedObjectUrl);
				ret.add(m);
				in.close();
			} catch (Exception e) {
				log.error("putObject,e:{}", e);
			}
		}

		return ret;
	}


	/**
	 * @param bucketName 存储桶名称
	 * @param objectName 文件名称
	 * @throws Exception
	 */
	public void  removeObject(String bucketName, String objectName) {
		try {
			minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
		} catch (Exception e) {
			log.error("removeObject,e:{}", e);
		}
	}
	/**
	 * 生成一个给HTTP GET请求用的presigned URL。
	 *      浏览器/移动端的客户端可以用这个URL进行下载,
	 *      即使其所在的存储桶是私有的。
	 *      这个presigned URL可以设置一个失效时间,默认值是7天
	 *
	 * @param bucketName 存储桶名称
	 * @param objectName 文件名称
	 * @param expiry     失效时间(单位小时)
	 * @return
	 */
	public String getPresignedObjectUrl(String bucketName, String objectName, Integer expiry) {
		log.info("bucketName = {}",bucketName);
		log.info("objectName = {}",objectName);
		log.info("expiry = {}",expiry);
		try {
			String presignedObjectUrl = minioClient.getPresignedObjectUrl(
					GetPresignedObjectUrlArgs
							.builder()
							.method(Method.GET)
							.bucket(bucketName)
							.object(objectName)
							.expiry(expiry, TimeUnit.HOURS)
							.build());
			log.info("presignedObjectUrl:{}", presignedObjectUrl);
			return presignedObjectUrl;
		} catch (Exception e) {
			log.error("getPresignedObjectUrl,e:{}", e);
		}
		return null;
	}


	public static String formatFileSize(long fileS) {
		DecimalFormat df = new DecimalFormat("#.00");
		String fileSizeString = "";
		if (fileS == 0) {
			return MinioService.FILESIZE_0B;
		}
		if (fileS < 1024) {
			fileSizeString = df.format((double) fileS) + " B";
		} else if (fileS < 1048576) {
			fileSizeString = df.format((double) fileS / 1024) + " KB";
		} else if (fileS < 1073741824) {
			fileSizeString = df.format((double) fileS / 1048576) + " MB";
		} else {
			fileSizeString = df.format((double) fileS / 1073741824) + " GB";
		}

		return fileSizeString;
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值