180 lines
4.2 KiB
Go
180 lines
4.2 KiB
Go
package oss
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
)
|
|
|
|
type S3ClientConfig struct {
|
|
Domain string
|
|
Region string
|
|
AccessKeyID string
|
|
SecretAccessKey string
|
|
BucketName string
|
|
Prefix string
|
|
}
|
|
|
|
var _ IClient = (*S3Client)(nil)
|
|
|
|
type S3Client struct {
|
|
config S3ClientConfig
|
|
session *session.Session
|
|
client *s3.S3
|
|
}
|
|
|
|
func NewS3Client(config S3ClientConfig) (*S3Client, error) {
|
|
awsConfig := aws.NewConfig()
|
|
awsConfig.WithRegion(config.Region)
|
|
awsConfig.WithCredentials(credentials.NewStaticCredentials(config.AccessKeyID, config.SecretAccessKey, ""))
|
|
session, err := session.NewSession(awsConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &S3Client{
|
|
config: config,
|
|
session: session,
|
|
client: s3.New(session),
|
|
}, nil
|
|
}
|
|
|
|
func (c *S3Client) PutObject(ctx context.Context, bucketName, objectName string, reader io.ReadSeeker, objectSize int64, options ...PutObjectOptions) (*PutObjectResult, error) {
|
|
if bucketName == "" {
|
|
bucketName = c.config.BucketName
|
|
}
|
|
|
|
var opt PutObjectOptions
|
|
if len(options) > 0 {
|
|
opt = options[0]
|
|
}
|
|
|
|
objectName = formatObjectName(c.config.Prefix, objectName)
|
|
input := &s3.PutObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(objectName),
|
|
Body: reader,
|
|
ContentType: aws.String(opt.ContentType),
|
|
ContentDisposition: aws.String("inline"),
|
|
ACL: aws.String("public-read"),
|
|
}
|
|
|
|
if len(opt.UserMetadata) > 0 {
|
|
input.Metadata = make(map[string]*string)
|
|
for k, v := range opt.UserMetadata {
|
|
input.Metadata[k] = aws.String(v)
|
|
}
|
|
}
|
|
|
|
output, err := c.client.PutObject(input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &PutObjectResult{
|
|
URL: c.config.Domain + "/" + objectName,
|
|
Key: *input.Key,
|
|
ETag: *output.ETag,
|
|
Size: objectSize,
|
|
}, nil
|
|
}
|
|
|
|
func (c *S3Client) GetObject(ctx context.Context, bucketName, objectName string) (io.ReadCloser, error) {
|
|
if bucketName == "" {
|
|
bucketName = c.config.BucketName
|
|
}
|
|
|
|
objectName = formatObjectName(c.config.Prefix, objectName)
|
|
input := &s3.GetObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(objectName),
|
|
}
|
|
|
|
output, err := c.client.GetObject(input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return output.Body, nil
|
|
}
|
|
|
|
func (c *S3Client) RemoveObject(ctx context.Context, bucketName, objectName string) error {
|
|
if bucketName == "" {
|
|
bucketName = c.config.BucketName
|
|
}
|
|
|
|
objectName = formatObjectName(c.config.Prefix, objectName)
|
|
input := &s3.DeleteObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(objectName),
|
|
}
|
|
|
|
_, err := c.client.DeleteObject(input)
|
|
return err
|
|
}
|
|
|
|
func (c *S3Client) RemoveObjectByURL(ctx context.Context, urlStr string) error {
|
|
prefix := c.config.Domain + "/"
|
|
if !strings.HasPrefix(urlStr, prefix) {
|
|
return nil
|
|
}
|
|
|
|
objectName := strings.TrimPrefix(urlStr, prefix)
|
|
input := &s3.DeleteObjectInput{
|
|
Bucket: aws.String(c.config.BucketName),
|
|
Key: aws.String(objectName),
|
|
}
|
|
|
|
_, err := c.client.DeleteObject(input)
|
|
return err
|
|
}
|
|
|
|
func (c *S3Client) StatObjectByURL(ctx context.Context, urlStr string) (*ObjectStat, error) {
|
|
prefix := c.config.Domain + "/"
|
|
if !strings.HasPrefix(urlStr, prefix) {
|
|
return nil, nil
|
|
}
|
|
|
|
objectName := strings.TrimPrefix(urlStr, prefix)
|
|
return c.StatObject(ctx, c.config.BucketName, objectName)
|
|
}
|
|
|
|
func (c *S3Client) StatObject(ctx context.Context, bucketName, objectName string) (*ObjectStat, error) {
|
|
if bucketName == "" {
|
|
bucketName = c.config.BucketName
|
|
}
|
|
|
|
objectName = formatObjectName(c.config.Prefix, objectName)
|
|
input := &s3.HeadObjectInput{
|
|
Bucket: aws.String(bucketName),
|
|
Key: aws.String(objectName),
|
|
}
|
|
|
|
output, err := c.client.HeadObject(input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var metadata map[string]string
|
|
if output.Metadata != nil {
|
|
metadata = make(map[string]string)
|
|
for k, v := range output.Metadata {
|
|
metadata[k] = *v
|
|
}
|
|
}
|
|
|
|
return &ObjectStat{
|
|
Key: objectName,
|
|
ETag: *output.ETag,
|
|
LastModified: *output.LastModified,
|
|
Size: *output.ContentLength,
|
|
ContentType: *output.ContentType,
|
|
UserMetadata: metadata,
|
|
}, nil
|
|
}
|