s3.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package s3
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "strings"
  8. "github.com/aws/aws-sdk-go-v2/aws"
  9. s3config "github.com/aws/aws-sdk-go-v2/config"
  10. "github.com/aws/aws-sdk-go-v2/credentials"
  11. "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
  12. awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
  13. "github.com/aws/aws-sdk-go-v2/service/s3/types"
  14. )
  15. type Config struct {
  16. AccessKey string
  17. SecretKey string
  18. Bucket string
  19. EndPoint string
  20. Region string
  21. URLPrefix string
  22. URLSuffix string
  23. }
  24. type Client struct {
  25. Client *awss3.Client
  26. Config *Config
  27. }
  28. func NewClient(ctx context.Context, config *Config) (*Client, error) {
  29. // For some s3-compatible object stores, converting the hostname is not required,
  30. // and not setting this option will result in not being able to access the corresponding object store address.
  31. // But Aliyun OSS should disable this option
  32. hostnameImmutable := true
  33. if strings.HasSuffix(config.EndPoint, "aliyuncs.com") {
  34. hostnameImmutable = false
  35. }
  36. resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...any) (aws.Endpoint, error) {
  37. return aws.Endpoint{
  38. URL: config.EndPoint,
  39. SigningRegion: config.Region,
  40. HostnameImmutable: hostnameImmutable,
  41. }, nil
  42. })
  43. awsConfig, err := s3config.LoadDefaultConfig(ctx,
  44. s3config.WithEndpointResolverWithOptions(resolver),
  45. s3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(config.AccessKey, config.SecretKey, "")),
  46. )
  47. if err != nil {
  48. return nil, err
  49. }
  50. client := awss3.NewFromConfig(awsConfig)
  51. return &Client{
  52. Client: client,
  53. Config: config,
  54. }, nil
  55. }
  56. func (client *Client) UploadFile(ctx context.Context, filename string, fileType string, src io.Reader) (string, error) {
  57. uploader := manager.NewUploader(client.Client)
  58. uploadOutput, err := uploader.Upload(ctx, &awss3.PutObjectInput{
  59. Bucket: aws.String(client.Config.Bucket),
  60. Key: aws.String(filename),
  61. Body: src,
  62. ContentType: aws.String(fileType),
  63. ACL: types.ObjectCannedACL(*aws.String("public-read")),
  64. })
  65. if err != nil {
  66. return "", err
  67. }
  68. link := uploadOutput.Location
  69. // If url prefix is set, use it as the file link.
  70. if client.Config.URLPrefix != "" {
  71. link = fmt.Sprintf("%s/%s%s", client.Config.URLPrefix, filename, client.Config.URLSuffix)
  72. }
  73. if link == "" {
  74. return "", errors.New("failed to get file link")
  75. }
  76. return link, nil
  77. }