🎉 开始项目

feat: 完成基础界面; 列表展示
todo: uplevel button function
todo: download/upload
This commit is contained in:
loveuer
2024-10-11 22:24:14 +08:00
commit 1c818daf16
76 changed files with 12517 additions and 0 deletions

101
internal/s3/list.go Normal file
View File

@ -0,0 +1,101 @@
package s3
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/samber/lo"
"strings"
"time"
)
type ListBucketRes struct {
CreatedAt int64 `json:"created_at"`
Name string `json:"name"`
}
type ListFileType int64
const (
ListFileTypeFile ListFileType = iota
ListFileTypeDir
)
type ListFileRes struct {
Name string `json:"name"`
Key string `json:"key"`
LastModified time.Time `json:"last_modified"`
Size int64 `json:"size"`
Type ListFileType `json:"type"`
}
func (c *Client) ListBucket(ctx context.Context) ([]*ListBucketRes, error) {
var (
err error
input = &s3.ListBucketsInput{
MaxBuckets: aws.Int32(100),
}
output *s3.ListBucketsOutput
)
if output, err = c.client.ListBuckets(ctx, input); err != nil {
return nil, err
}
res := lo.Map(
output.Buckets,
func(item types.Bucket, index int) *ListBucketRes {
return &ListBucketRes{CreatedAt: item.CreationDate.UnixMilli(), Name: *item.Name}
},
)
return res, nil
}
func (c *Client) ListFile(ctx context.Context, bucket string, prefix string) ([]*ListFileRes, error) {
var (
err error
input = &s3.ListObjectsV2Input{
Delimiter: aws.String("/"),
MaxKeys: aws.Int32(1000),
Bucket: aws.String(bucket),
}
output *s3.ListObjectsV2Output
)
if prefix != "" {
input.Prefix = aws.String(prefix)
}
if output, err = c.client.ListObjectsV2(ctx, input); err != nil {
return nil, err
}
folder := lo.FilterMap(
output.CommonPrefixes,
func(item types.CommonPrefix, index int) (*ListFileRes, bool) {
name := strings.TrimPrefix(*item.Prefix, prefix)
return &ListFileRes{
Name: name,
Key: *item.Prefix,
Type: ListFileTypeDir,
}, name != ""
},
)
list := lo.Map(
output.Contents,
func(item types.Object, index int) *ListFileRes {
return &ListFileRes{
Key: strings.Clone(*item.Key),
Name: strings.TrimPrefix(*item.Key, prefix),
LastModified: *item.LastModified,
Size: *item.Size,
Type: ListFileTypeFile,
}
},
)
return append(folder, list...), nil
}

72
internal/s3/s3.go Normal file
View File

@ -0,0 +1,72 @@
package s3
import (
"context"
"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/service/s3"
smithyendpoints "github.com/aws/smithy-go/endpoints"
"github.com/loveuer/nf-disk/internal/tool"
"github.com/loveuer/nf/nft/log"
"net/url"
)
type resolverV2 struct{}
func (*resolverV2) ResolveEndpoint(ctx context.Context, params s3.EndpointParameters) (smithyendpoints.Endpoint, error) {
u, err := url.Parse(*params.Endpoint)
if err != nil {
log.Warn("resolver v2: parse url = %s, err = %s", params.Endpoint, err.Error())
return smithyendpoints.Endpoint{}, err
}
return smithyendpoints.Endpoint{
URI: *u,
}, nil
}
type Client struct {
client *s3.Client
}
func New(ctx context.Context, endpoint string, access string, key string) (*Client, error) {
var (
err error
sdkConfig aws.Config
output *s3.ListBucketsOutput
)
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: endpoint,
}, nil
})
if sdkConfig, err = config.LoadDefaultConfig(
ctx,
config.WithEndpointResolverWithOptions(customResolver),
); err != nil {
return nil, err
}
s3Client := s3.NewFromConfig(sdkConfig, func(o *s3.Options) {
//o.BaseEndpoint = aws.String(endpoint)
//o.EndpointResolverV2 = &resolverV2{}
o.Credentials = aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(access, key, ""))
o.UsePathStyle = true
o.Region = "auto"
})
if output, err = s3Client.ListBuckets(tool.Timeout(5), &s3.ListBucketsInput{
MaxBuckets: aws.Int32(2),
}); err != nil {
return nil, err
}
for _, item := range output.Buckets {
log.Debug("s3.New: list bucket name = %s", *item.Name)
}
return &Client{client: s3Client}, nil
}

37
internal/s3/s3_test.go Normal file
View File

@ -0,0 +1,37 @@
package s3
import (
"context"
"github.com/loveuer/nf-disk/internal/tool"
"github.com/loveuer/nf/nft/log"
"testing"
)
func TestNewClient(t *testing.T) {
log.SetLogLevel(log.LogLevelDebug)
_, err := New(context.TODO(), "http://10.220.10.15:9000/", "8ALV3DUZI31YG4BDRJ0Z", "CRqwS1MsiUj27TbRK+3T2n+LpKWd07VvaDKuzU0H")
if err != nil {
t.Fatalf("call s3.New err = %s", err.Error())
}
}
func TestListFile(t *testing.T) {
//log.SetLogLevel(log.LogLevelDebug)
//cli, err := New(context.TODO(), "http://10.220.10.14:19000", "5VCR05L4BSGNCTCD8DXP", "FPTMYBEiHhWLJ05C3aGXW8bjFXXNmghc8Za3Fo2u")
cli, err := New(context.TODO(), "http://10.220.10.15:9000/", "8ALV3DUZI31YG4BDRJ0Z", "CRqwS1MsiUj27TbRK+3T2n+LpKWd07VvaDKuzU0H")
if err != nil {
t.Fatalf("call s3.New err = %s", err.Error())
}
files, err := cli.ListFile(tool.Timeout(30), "topic-audit", "")
if err != nil {
t.Fatalf("call s3.ListFile err = %s", err.Error())
}
t.Logf("[x] file length = %d", len(files))
for _, item := range files {
t.Logf("[x: %d] file = %s, size = %d", item.Type, item.Name, item.Size)
}
}