123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package store
- import (
- "bytes"
- "context"
- "errors"
- "github.com/minio/minio-go"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "strings"
- "sync"
- )
- var once sync.Once
- // ErrorInvalidName 无效的文件名
- var ErrorInvalidName = errors.New("invalid file name")
- // MinioStore minio 对象存储
- type MinioStore struct {
- cli *minio.Client
- }
- // ComposeObject 通过使用服务端拷贝实现钭多个源对象合并创建成一个新的对象。
- func (m *MinioStore) ComposeObject(ctx context.Context,pathS []string,filePath string) error {
- bucketName,fileName,err := m.parseFilename(filePath)
- if err != nil{
- return err
- }
- dst, err := minio.NewDestinationInfo(bucketName, fileName, nil, nil)
- if err != nil {
- return err
- }
- srcs := make([]minio.SourceInfo,0,len(pathS))
- for i:=range pathS{
- bucketName,fileName,err := m.parseFilename(pathS[i])
- if err != nil{
- return err
- }
- srcs = append(srcs,minio.NewSourceInfo(bucketName, fileName, nil))
- }
- return m.cli.ComposeObject(dst, srcs)
- }
- //RemoveObject 删除minio中的文件
- func (m *MinioStore) RemoveObject(ctx context.Context,filePath string) error {
- bucketName,fileName,err := m.parseFilename(filePath)
- if err != nil{
- return err
- }
- return m.cli.RemoveObject(bucketName, fileName)
- }
- func (m *MinioStore) Delete(ctx context.Context, fileName string) error {
- b, o, err := m.parseFilename(fileName)
- if err != nil {
- return err
- }
- n, err := url.PathUnescape(o)
- if err != nil {
- return err
- }
- return m.cli.RemoveObject(b, n)
- }
- // Stat 文件状态信息
- func (m *MinioStore) Stat(filename string) (minio.ObjectInfo, error) {
- bucketName, objectName, err := m.parseFilename(filename)
- if err != nil {
- return minio.ObjectInfo{}, err
- }
- return m.cli.StatObject(bucketName, objectName, minio.StatObjectOptions{})
- }
- // Get get file buffers
- func (m *MinioStore) Get(ctx context.Context, fileName string) ([]byte, string, error) {
- if ctx == nil {
- ctx = context.Background()
- }
- stat, err := m.Stat(fileName)
- if err != nil {
- return nil, "", errors.New("文件不存在:" + fileName)
- }
- bucketName, objectName, err := m.parseFilename(fileName)
- if err != nil {
- return nil, "", err
- }
- obj, err := m.cli.GetObjectWithContext(ctx, bucketName, objectName, minio.GetObjectOptions{})
- if err != nil {
- return nil, "", err
- }
- buf, err := ioutil.ReadAll(obj)
- if err != nil {
- return nil, "", err
- }
- return buf, stat.ContentType, nil
- }
- // Store save file
- func (m *MinioStore) Store(ctx context.Context, filename string, data io.Reader, size int64) (fileHash string, err error) {
- if ctx == nil {
- ctx = context.Background()
- }
- bucket, objName, err := m.parseFilename(filename)
- if err != nil {
- return
- }
- exists, err := m.cli.BucketExists(bucket)
- if err != nil {
- return
- } else if !exists {
- err = m.cli.MakeBucket(bucket, "local")
- if err != nil {
- return
- }
- }
- buf, err := ioutil.ReadAll(data)
- if err != nil {
- return
- }
- rd := bytes.NewBuffer(buf)
- if size == 0 {
- size = int64(rd.Len())
- }
- _, err = m.cli.PutObjectWithContext(ctx, bucket, objName, rd, size, minio.PutObjectOptions{
- ContentType: http.DetectContentType(buf),
- NumThreads: 2,
- })
- stat, err := m.Stat(filename)
- if err != nil {
- return
- }
- fileHash = stat.ETag
- return
- }
- // 解析文件名 `prefix/bucket/uuid/filename`
- func (m *MinioStore) parseFilename(filename string) (string, string, error) {
- if len(filename) > 0 && filename[0] == '/' {
- filename = filename[1:]
- }
- names := strings.Split(filename, "/")
- if len(names) < 3 {
- return "", "", ErrorInvalidName
- }
- return strings.ToLower(names[1]), strings.Join(names[2:], "/"), nil
- }
- // MiniStoreInit minio init
- func MiniStoreInit(addr, accessKey, secretKey string) *MinioStore {
- ms := new(MinioStore)
- once.Do(func() {
- cli, err := minio.New(addr, accessKey, secretKey, false)
- if err != nil {
- panic(err)
- }
- ms.cli = cli
- })
- return ms
- }
|