1
1
mirror of https://github.com/usememos/memos.git synced 2024-12-22 18:51:31 +03:00
memos/plugin/storage/s3/s3.go

92 lines
2.5 KiB
Go
Raw Normal View History

package s3
import (
"context"
2023-09-17 17:55:13 +03:00
"errors"
"fmt"
"io"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
2023-02-23 19:02:51 +03:00
s3config "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
)
2023-02-23 19:02:51 +03:00
type Config struct {
AccessKey string
SecretKey string
Bucket string
EndPoint string
Region string
URLPrefix string
URLSuffix string
2023-02-23 19:02:51 +03:00
}
type Client struct {
2023-02-23 19:02:51 +03:00
Client *awss3.Client
Config *Config
}
2023-02-23 19:02:51 +03:00
func NewClient(ctx context.Context, config *Config) (*Client, error) {
// For some s3-compatible object stores, converting the hostname is not required,
// and not setting this option will result in not being able to access the corresponding object store address.
// But Aliyun OSS should disable this option
hostnameImmutable := true
if strings.HasSuffix(config.EndPoint, "aliyuncs.com") {
hostnameImmutable = false
}
resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...any) (aws.Endpoint, error) {
return aws.Endpoint{
URL: config.EndPoint,
SigningRegion: config.Region,
HostnameImmutable: hostnameImmutable,
}, nil
})
awsConfig, err := s3config.LoadDefaultConfig(ctx,
2023-02-23 19:02:51 +03:00
s3config.WithEndpointResolverWithOptions(resolver),
s3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKey, config.SecretKey, "")),
)
if err != nil {
return nil, err
}
client := awss3.NewFromConfig(awsConfig)
return &Client{
2023-02-23 19:02:51 +03:00
Client: client,
Config: config,
}, nil
}
2023-02-23 19:02:51 +03:00
func (client *Client) UploadFile(ctx context.Context, filename string, fileType string, src io.Reader) (string, error) {
uploader := manager.NewUploader(client.Client)
2023-11-24 16:55:09 +03:00
putInput := awss3.PutObjectInput{
2023-02-23 19:02:51 +03:00
Bucket: aws.String(client.Config.Bucket),
Key: aws.String(filename),
Body: src,
ContentType: aws.String(fileType),
}
2023-11-24 16:55:09 +03:00
// Set ACL according to if url prefix is set.
if client.Config.URLPrefix == "" {
2023-11-24 16:55:09 +03:00
putInput.ACL = types.ObjectCannedACL(*aws.String("public-read"))
}
2023-11-24 16:55:09 +03:00
uploadOutput, err := uploader.Upload(ctx, &putInput)
if err != nil {
return "", err
}
link := uploadOutput.Location
2023-03-04 15:06:32 +03:00
// If url prefix is set, use it as the file link.
if client.Config.URLPrefix != "" {
link = fmt.Sprintf("%s/%s%s", client.Config.URLPrefix, filename, client.Config.URLSuffix)
}
2023-03-04 15:06:32 +03:00
if link == "" {
2023-09-17 17:55:13 +03:00
return "", errors.New("failed to get file link")
2023-03-04 15:06:32 +03:00
}
return link, nil
}