Minio SDK

地址: https://github.com/minio/minio-go

单文件上传

package main

import (
	"context"
	"log"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {

	// 创建 minio 客户端对象连接
	endpoint := "192.168.0.221:9000"
	accessKey := "tvR7984WQeZZig2tWkgE"
	secretKey := "Tf0qT98Yh6oGCqqAvHEUVn0liskCe2CHHrhrL1LL"
	useSSL := false

	minioClient, err := minio.New(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKey, secretKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatalln("创建客户端失败: " + err.Error())
	}

	// 上传文件
	// 1.创建桶 (bucket)
	bucketName := "test-bucket"
	location := "company_221_docker"

	err = minioClient.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{Region: location})
	if err != nil {
		// 检查桶是否已经存在
		exist, existErr := minioClient.BucketExists(context.Background(), bucketName)
		if existErr == nil && exist {
			log.Printf("Bucket %s already exists.\n", bucketName)
		} else {
			log.Fatalln("创建桶失败: " + err.Error())
		}
	}

	log.Printf("Successfully created %s\n", bucketName)

	// 2.上传文件对象
	filePath := "/Users/yw/Project/go/demo/minio/credentials.json"
	uploadFileName := "test-001.json"
	contentType := "application/json"

	info, err := minioClient.FPutObject(context.Background(), bucketName, uploadFileName, filePath, minio.PutObjectOptions{ContentType: contentType})
	if err != nil {
		log.Fatalln("上传文件失败" + err.Error())

	}

	log.Printf("Successfully uploaded %s of size %d\n", uploadFileName, info.Size)

}

分片上传

分片上传使用的 client 对象是 minioCore 对象,该对象提供了更底层的 AWS S3 的方法,分片上传也在这里提供。

package main

import (
	"context"
	"log"
	"net/url"
	"time"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建 minio 客户端对象连接
	endpoint := "192.168.0.221:9000"
	accessKey := "tvR7984WQeZZig2tWkgE"
	secretKey := "Tf0qT98Yh6oGCqqAvHEUVn0liskCe2CHHrhrL1LL"
	useSSL := false

	minioCore, err := minio.NewCore(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKey, secretKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatal("创建客户端失败: " + err.Error())
	}

	bucketName := "test-bucket"
	fileObjName := "测试文件名称.mov"

	ctx := context.Background()

	uploadID, err := minioCore.NewMultipartUpload(ctx, bucketName, fileObjName, minio.PutObjectOptions{})
	if err != nil {
		log.Fatal("获取上传 ID 失败: " + err.Error())
	}

	log.Println("上传 ID: " + uploadID)

	// 模拟文件切分后-五个分片
	// 貌似 url.Values 可以置空,实际前端请求时 并不需要携带这两个自定义参数
	for partNum := 1; partNum <= 5; partNum++ {
		// partUploadURL, err := minioCore.Presign(ctx, "POST", bucketName, fileObjName, time.Hour, url.Values{
		// 	"uploadId":   []string{uploadID},
		// 	"partNumber": []string{strconv.Itoa(partNum)},
		// })

		partUploadURL, err := minioCore.Presign(ctx, "POST", bucketName, fileObjName, time.Hour, url.Values{})
		if err != nil {
			log.Fatal("获取上传地址失败: " + err.Error())

		}
		log.Println("上传地址: " + partUploadURL.String())
	}

	// 返回所有的上传分片链接给前端
	// 前端使用 post 方法, formData 向改地址提交文件分片数据
	// 提交之后获取上传的 Etag 信息,并与其分片序号一起保存下来,后面合并代码时会需要

}

中止分片上传

package main

import (
	"context"
	"log"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建 minio 客户端对象连接
	endpoint := "192.168.0.221:9000"
	accessKey := "tvR7984WQeZZig2tWkgE"
	secretKey := "Tf0qT98Yh6oGCqqAvHEUVn0liskCe2CHHrhrL1LL"
	useSSL := false

	minioCore, err := minio.NewCore(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKey, secretKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatal("创建客户端失败: " + err.Error())
	}

	bucketName := "test-bucket"
	fileObjName := "测试文件名称.mov"
	// uploadID := "MjM3NmQ2NzMtMTQ5OS00MTkzLWJjMGMtYWRjNjFiNzBiNjJlLjc2OWIwZmU4LTNhMDctNGQyNi04YmQ1LTM0YTA5MzU3MTA0Mg"
	uploadID := "MjM3NmQ2NzMtMTQ5OS00MTkzLWJjMGMtYWRjNjFiNzBiNjJlLmQ4Yjk1YzIzLTM2OTItNDFiNi1hOTEzLTgwYjRkYTljNTQ2Mw"

	ctx := context.Background()

	if err := minioCore.AbortMultipartUpload(ctx, bucketName, fileObjName, uploadID); err != nil {
		log.Fatal("终止分片上传失败: " + err.Error())

	}
	log.Println("终止分片上传成功")
}

合并文件

package main

import (
	"context"
	"log"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建 minio 客户端对象连接
	endpoint := "192.168.0.221:9000"
	accessKey := "tvR7984WQeZZig2tWkgE"
	secretKey := "Tf0qT98Yh6oGCqqAvHEUVn0liskCe2CHHrhrL1LL"
	useSSL := false

	minioCore, err := minio.NewCore(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKey, secretKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatal("创建客户端失败: " + err.Error())
	}

	bucketName := "test-bucket"
	fileObjName := "测试文件名称.mov"
	uploadID := "MjM3NmQ2NzMtMTQ5OS00MTkzLWJjMGMtYWRjNjFiNzBiNjJlLjc2OWIwZmU4LTNhMDctNGQyNi04YmQ1LTM0YTA5MzU3MTA0Mg"

	ctx := context.Background()

	// PartNumber 分片的序号
	// ETag 分片的ETag 分片校验码,前端上传文件分片之后,返回的校验码
	// CompletePart 的顺序必须是 分片序号的 升序排序
	info, err := minioCore.CompleteMultipartUpload(ctx, bucketName, fileObjName, uploadID, []minio.CompletePart{
		{PartNumber: 1, ETag: "etag1"},
		{PartNumber: 2, ETag: "etag2"},
	}, minio.PutObjectOptions{})
	if err != nil {
		log.Fatal("分片上传合并失败: " + err.Error())

	}

	log.Println("分片上传合并成功: ", info)
}

前端直连下载

预签名下载链接,丢给前端直接下载即可。同理还有单文件上传也可以预签名丢给前端。

package main

import (
	"context"
	"log"
	"net/url"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	// 创建 minio 客户端对象连接
	endpoint := "192.168.0.221:9000"
	accessKey := "tvR7984WQeZZig2tWkgE"
	secretKey := "Tf0qT98Yh6oGCqqAvHEUVn0liskCe2CHHrhrL1LL"
	useSSL := false

	minioCore, err := minio.NewCore(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKey, secretKey, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatal("创建客户端失败: " + err.Error())
	}

	bucketName := "test-bucket"
	fileObjName := "测试文件名称.mov"

	minioCore.PresignedGetObject(context.Background(), bucketName, fileObjName, 60, url.Values{})
}