本文主要介绍go语言使用Minio对象存储,首先介绍搭建minio,创建bucket等,然后讲解封装minio客户端接口,包括但不限于:上传文件,下载,获取对象url,最后测试开发的接口
文章目录
- 前言
 - Minio
 - docker安装minio
 - 创建bucket,指定accesskey等
 
- 客户端接口封装
 - 代码测试
 
前言
Minio是一个开源的对象存储服务器,旨在提供高性能、可扩展和易于使用的存储解决方案。它兼容Amazon S3 API,因此可以与现有的S3工具和库集成,同时也提供了一套丰富的客户端SDK。
以下是Minio的一些主要特点:
-  
分布式架构: Minio支持分布式部署,可以通过添加更多的节点来实现容量和性能的无缝扩展。它使用一致性哈希算法来分配对象到不同的节点上,从而实现负载均衡和数据冗余。
 -  
高性能: Minio采用了并发、异步和流式处理等技术,在保持数据完整性的同时,提供了出色的读写性能。它还支持多线程分段上传和下载,以加快大文件的传输速度。
 -  
数据安全: Minio提供了多种数据保护机制,包括数据加密、访问控制列表(ACL)、策略和签名等。它还支持SSL/TLS加密传输,确保数据在传输过程中的安全性。
 -  
易于使用: Minio提供了简单而直观的API,可以轻松地进行对象存储操作,如创建存储桶、上传和下载文件、删除对象等。它还提供了Web管理界面,方便用户进行管理和监控。
 -  
多语言支持: Minio提供了多种编程语言的客户端SDK,包括Go、Java、Python、JavaScript等,使开发人员可以在不同的平台上使用自己熟悉的语言与Minio进行交互。
 -  
可扩展性: Minio可以轻松地与其他存储系统集成,如分布式文件系统、块存储和对象存储等。它还支持动态缩放和容器化部署,以适应不同规模和需求的应用场景。
 
Minio
docker安装minio
docker介绍和常用命令使用请参考:docker常用命令介绍
具体搭建步骤可以参考:docker安装minio
docker run -p 9000:9000 -p 9090:9090 \
 --name minio \
 -d --restart=always \
 -e "MINIO_ACCESS_KEY=admin" \
 -e "MINIO_SECRET_KEY=123456" \
 -v /root/docker/minio/data:/data  \
 -v /root/docker/minio/config:/root/.minio \
 minio/minio  server\
 /data --console-address ":9090" -address ":9000"
 
启动成功:

创建bucket,指定accesskey等
网页访问:http://localhost:9090/,端口号9090修改为你指定的端口号,一般常用9090或者9000。
红圈地方用于创建AccessKey和SecretKey,注意记得备份一下额~
 
 创建Buckets:
 
客户端接口封装
这里封装了上传、下载、删除、列出指定buckets下的对象等常规接口,可以按照自己的需求更改~
package utils
import (
	"fmt"
	"github.com/minio/minio-go"
	"log"
	"os"
)
var MinioClientGlobal *MinioClient
type MinioClient struct {
	Client *minio.Client
}
// NewMinioClient 初始化minio
func NewMinioClient(endpoint, accessKey, secretKey string) (*MinioClient, error) {
	// 初始化 Minio 客户端
	minioClient, err := minio.New(endpoint, accessKey, secretKey, false)
	if err != nil {
		log.Println("new minio client fail: ", err)
		return nil, err
	}
	client := &MinioClient{
		Client: minioClient,
	}
	MinioClientGlobal = client
	return client, nil
}
// UploadFile 上传文件
func (m *MinioClient) UploadFile(bucketName, objectName, filePath string) error {
	// 打开本地文件
	file, err := os.Open(filePath)
	if err != nil {
		log.Printf("open filePath: %s fail: %s", filePath, err)
		return err
	}
	defer file.Close()
	// 上传文件到存储桶
	_, err = m.Client.PutObject(bucketName, objectName, file, -1, minio.PutObjectOptions{})
	if err != nil {
		log.Println("putObject fail: ", err)
		return err
	}
	fmt.Println("Successfully uploaded", objectName)
	return nil
}
// DownloadFile 下载文件
func (m *MinioClient) DownloadFile(bucketName, objectName, filePath string) error {
	// 创建本地文件
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()
	// 下载存储桶中的文件到本地
	err = m.Client.FGetObject(bucketName, objectName, filePath, minio.GetObjectOptions{})
	if err != nil {
		return err
	}
	fmt.Println("Successfully downloaded", objectName)
	return nil
}
// DeleteFile 删除文件
func (m *MinioClient) DeleteFile(bucketName, objectName string) (bool, error) {
	// 删除存储桶中的文件
	err := m.Client.RemoveObject(bucketName, objectName)
	if err != nil {
		log.Println("remove object fail: ", err)
		return false, err
	}
	fmt.Println("Successfully deleted", objectName)
	return true, err
}
// ListObjects 列出文件
func (m *MinioClient) ListObjects(bucketName, prefix string) ([]string, error) {
	var objectNames []string
	for object := range m.Client.ListObjects(bucketName, prefix, true, nil) {
		if object.Err != nil {
			return nil, object.Err
		}
		objectNames = append(objectNames, object.Key)
	}
	return objectNames, nil
}
// GetPresignedGetObject 返回对象的url地址,有效期时间为expires
func (m *MinioClient) GetPresignedGetObject(bucketName string, objectName string, expires time.Duration) (string, error) {
	object, err := m.Client.PresignedGetObject(bucketName, objectName, expires, nil)
	if err != nil {
		log.Println("get object fail: ", err)
		return "", err
	}
	return object.String(), nil
}
 
代码测试
如何编写测试代码,可以参考【go语言开发】编写单元测试
下面是minio的配置,替换成自己的就可以
[minio]
MinioEndPoint = 127.0.0.1:9000
MinioAccessKey = NLtS0iNRFSCv6umJ
MinioSecretKey = 0cFaw1C0rp2CvhNIKYvAlqKrHNMB1rkn
MinioBucketName = go-blog
 
package test
import (
	"gin-blog/utils"
	"log"
	"testing"
)
const (
	filePath         = "./assets/test.txt"
	objectName       = "test.txt"
	downloadFilePath = "./assets/test2.txt"
)
// MinioInitTest 初始化minio client
func MinioInitTest() *utils.MinioClient {
	// 加载minio的endpoint等
	utils.InitConfig()
	log.Println(utils.MinioEndPoint, utils.MinioAccessKey, utils.MinioSecretKey)
	client, err := utils.NewMinioClient(utils.MinioEndPoint, utils.MinioAccessKey, utils.MinioSecretKey)
	if err != nil {
		log.Println("init minio fail")
		return nil
	}
	return client
}
// 测试上传文件
func TestMinioUpload(t *testing.T) {
	client := MinioInitTest()
	err := client.UploadFile(utils.MinioBucketName, objectName, filePath)
	if err != nil {
		t.Error("upload file: ", err)
	}
}
// 测试下载文件
func TestMinioDownloadFile(t *testing.T) {
	client := MinioInitTest()
	err := client.DownloadFile(utils.MinioBucketName, objectName, downloadFilePath)
	if err != nil {
		t.Error("download file: ", err)
	}
}
// 测试列出bucket下所有的对象
func TestListObjects(t *testing.T) {
	client := MinioInitTest()
	objects, err := client.ListObjects(utils.MinioBucketName, "")
	if err != nil {
		t.Error("list object: ", err)
	}
	log.Println("objects: ", objects)
}
// 删除对象
func TestDeleteFile(t *testing.T) {
	client := MinioInitTest()
	ret, err := client.DeleteFile(utils.MinioBucketName, objectName)
	if err != nil {
		t.Error("delete object: ", ret, err)
	}
	log.Println("delete object: ", ret)
}
// 获取对象,返回url,
func TestGetPresignedGetObject(t *testing.T) {
	client := MinioInitTest()
	object, err := client.GetPresignedGetObject(utils.MinioBucketName, objectName, 24*time.Hour)
	if err != nil {
		t.Error("GetPresignedGetObject: ", err)
	}
	log.Println("GetPresignedGetObject: ", object)
}
 
所有的接口都已经测试
上传文件:
 
 
获取对象url:
 



















