init commit
This commit is contained in:
92
plugin/storage/s3/s3.go
Normal file
92
plugin/storage/s3/s3.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"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"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
storepb "github.com/usememos/memos/proto/gen/store"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Client *s3.Client
|
||||
Bucket *string
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, s3Config *storepb.StorageS3Config) (*Client, error) {
|
||||
cfg, err := config.LoadDefaultConfig(ctx,
|
||||
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(s3Config.AccessKeyId, s3Config.AccessKeySecret, "")),
|
||||
config.WithRegion(s3Config.Region),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load s3 config")
|
||||
}
|
||||
|
||||
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||
o.BaseEndpoint = aws.String(s3Config.Endpoint)
|
||||
o.UsePathStyle = s3Config.UsePathStyle
|
||||
o.RequestChecksumCalculation = aws.RequestChecksumCalculationWhenRequired
|
||||
o.ResponseChecksumValidation = aws.ResponseChecksumValidationWhenRequired
|
||||
})
|
||||
return &Client{
|
||||
Client: client,
|
||||
Bucket: aws.String(s3Config.Bucket),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UploadObject uploads an object to S3.
|
||||
func (c *Client) UploadObject(ctx context.Context, key string, fileType string, content io.Reader) (string, error) {
|
||||
uploader := manager.NewUploader(c.Client)
|
||||
putInput := s3.PutObjectInput{
|
||||
Bucket: c.Bucket,
|
||||
Key: aws.String(key),
|
||||
ContentType: aws.String(fileType),
|
||||
Body: content,
|
||||
}
|
||||
result, err := uploader.Upload(ctx, &putInput)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resultKey := result.Key
|
||||
if resultKey == nil || *resultKey == "" {
|
||||
return "", errors.New("failed to get file key")
|
||||
}
|
||||
return *resultKey, nil
|
||||
}
|
||||
|
||||
// PresignGetObject presigns an object in S3.
|
||||
func (c *Client) PresignGetObject(ctx context.Context, key string) (string, error) {
|
||||
presignClient := s3.NewPresignClient(c.Client)
|
||||
presignResult, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(*c.Bucket),
|
||||
Key: aws.String(key),
|
||||
}, func(opts *s3.PresignOptions) {
|
||||
// Set the expiration time of the presigned URL to 5 days.
|
||||
// Reference: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
|
||||
opts.Expires = time.Duration(5 * 24 * time.Hour)
|
||||
})
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to presign put object")
|
||||
}
|
||||
return presignResult.URL, nil
|
||||
}
|
||||
|
||||
// DeleteObject deletes an object in S3.
|
||||
func (c *Client) DeleteObject(ctx context.Context, key string) error {
|
||||
_, err := c.Client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
Bucket: c.Bucket,
|
||||
Key: aws.String(key),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to delete object")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user