admin e596e388b4
All checks were successful
continuous-integration/drone/push Build is passing
v0.0.27.5
2025-08-28 13:15:13 +03:00

106 lines
2.8 KiB
Go

package S3
import (
"context"
"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
awsConfig "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"
)
// Получаем S3 клиент
func getS3Client() (*s3.Client, error) {
cfg, err := awsConfig.LoadDefaultConfig(context.TODO(),
awsConfig.WithRegion("ru-central1"),
awsConfig.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
"TJ946G2S1Z5FEI3I7DQQ",
"C2H2aITHRDpek8H921yhnrINZwDoADsjW3F6HURl",
"",
)),
)
if err != nil {
return nil, err
}
// Используем virtual-hosted-style endpoint
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String("https://tailly.website.regru.cloud")
o.UsePathStyle = false // Отключаем path-style
})
return client, nil
}
func DeleteFromS3(imageURL string) error {
const op = "s3.DeleteFromS3"
parts := strings.SplitN(strings.TrimPrefix(imageURL, "https://s3.regru.cloud/"), "/", 2)
if len(parts) != 2 {
return fmt.Errorf("%s: invalid S3 URL format", op)
}
bucket := parts[0]
key := parts[1]
client, err := getS3Client()
if err != nil {
return fmt.Errorf("%s: failed to create S3 client: %w", op, err)
}
_, err = client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
})
if err != nil {
return fmt.Errorf("%s: failed to delete object from S3: %w", op, err)
}
// Ждем пока объект исчезнет
waiter := s3.NewObjectNotExistsWaiter(client)
err = waiter.Wait(context.TODO(), &s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}, 30*time.Second)
if err != nil {
return fmt.Errorf("%s: failed to wait for object deletion: %w", op, err)
}
return nil
}
func GeneratePresignedUploadURL(userID int, filename string) (string, string, error) {
const op = "s3.GeneratePresignedUploadURL"
client, err := getS3Client()
if err != nil {
return "", "", fmt.Errorf("%s: failed to create S3 client: %w", op, err)
}
uniqueKey := fmt.Sprintf("posts/%d/%d_%s", userID, time.Now().UnixNano(), filename)
presignClient := s3.NewPresignClient(client)
result, err := presignClient.PresignPutObject(context.TODO(),
&s3.PutObjectInput{
Bucket: aws.String("tailly"),
Key: aws.String(uniqueKey),
ContentLength: aws.Int64(10 * 1024 * 1024),
// Добавляем CORS headers через метаданные
Metadata: map[string]string{
"Access-Control-Allow-Origin": "https://tailly.ru",
"Access-Control-Allow-Methods": "PUT, POST, DELETE",
"Access-Control-Allow-Headers": "*",
},
},
s3.WithPresignExpires(15*time.Minute),
)
if err != nil {
return "", "", fmt.Errorf("%s: failed to generate presigned URL: %w", op, err)
}
return result.URL, uniqueKey, nil
}