@@ -2,23 +2,25 @@ package storage
22
33import (
44 "bytes"
5+ "context"
56 "fmt"
67 "io"
78 "log"
89 "mime/multipart"
910 "net/http"
1011 "strings"
12+ "time"
1113
12- "github.com/aws/aws-sdk-go/aws"
13- "github.com/aws/aws-sdk-go/aws/credentials "
14- "github.com/aws/aws-sdk-go/aws/session "
15- "github.com/aws/aws-sdk-go/service/s3"
14+ "github.com/aws/aws-sdk-go-v2 /aws"
15+ "github.com/aws/aws-sdk-go-v2/config "
16+ "github.com/aws/aws-sdk-go-v2/credentials "
17+ "github.com/aws/aws-sdk-go-v2 /service/s3"
1618 "github.com/gin-gonic/gin"
1719)
1820
1921// S3StorageStrategy S3 存储策略实现
2022type S3StorageStrategy struct {
21- client * s3.S3
23+ client * s3.Client
2224 bucketName string
2325 basePath string
2426 hostname string
@@ -31,31 +33,41 @@ func NewS3StorageStrategy(accessKeyID, secretAccessKey, bucketName, endpointURL,
3133 return nil , fmt .Errorf ("S3 bucket name cannot be empty" )
3234 }
3335
34- // 创建AWS会话配置
35- awsConfig := & aws.Config {
36- Region : aws .String (regionName ),
37- }
36+ ctx := context .Background ()
3837
39- // 如果有自定义endpoint
40- if endpointURL != "" {
41- awsConfig .Endpoint = aws .String (endpointURL )
42- awsConfig .S3ForcePathStyle = aws .Bool (true ) // 对于自定义endpoint,通常需要path style
38+ // 创建配置选项
39+ var optFns []func (* config.LoadOptions ) error
40+
41+ // 设置区域
42+ if regionName != "" {
43+ optFns = append (optFns , config .WithRegion (regionName ))
4344 }
4445
4546 // 设置凭证
4647 if accessKeyID != "" && secretAccessKey != "" {
47- creds := credentials .NewStaticCredentials (accessKeyID , secretAccessKey , sessionToken )
48- awsConfig . Credentials = creds
48+ creds := credentials .NewStaticCredentialsProvider (accessKeyID , secretAccessKey , sessionToken )
49+ optFns = append ( optFns , config . WithCredentialsProvider ( creds ))
4950 }
5051
51- // 创建会话
52- sess , err := session . NewSession ( awsConfig )
52+ // 加载配置
53+ cfg , err := config . LoadDefaultConfig ( ctx , optFns ... )
5354 if err != nil {
54- return nil , fmt .Errorf ("failed to create AWS session: %w" , err )
55+ return nil , fmt .Errorf ("failed to load AWS config: %w" , err )
56+ }
57+
58+ // 创建S3客户端选项
59+ var s3OptFns []func (* s3.Options )
60+
61+ // 如果有自定义endpoint
62+ if endpointURL != "" {
63+ s3OptFns = append (s3OptFns , func (o * s3.Options ) {
64+ o .BaseEndpoint = aws .String (endpointURL )
65+ o .UsePathStyle = true // 对于自定义endpoint,通常需要path style
66+ })
5567 }
5668
5769 // 创建S3客户端
58- client := s3 .New ( sess )
70+ client := s3 .NewFromConfig ( cfg , s3OptFns ... )
5971
6072 strategy := & S3StorageStrategy {
6173 client : client ,
@@ -82,7 +94,7 @@ func (ss *S3StorageStrategy) buildKey(relativePath string) string {
8294func (ss * S3StorageStrategy ) WriteFile (path string , data []byte ) error {
8395 key := ss .buildKey (path )
8496
85- _ , err := ss .client .PutObject (& s3.PutObjectInput {
97+ _ , err := ss .client .PutObject (context . Background (), & s3.PutObjectInput {
8698 Bucket : aws .String (ss .bucketName ),
8799 Key : aws .String (key ),
88100 Body : bytes .NewReader (data ),
@@ -95,7 +107,7 @@ func (ss *S3StorageStrategy) WriteFile(path string, data []byte) error {
95107func (ss * S3StorageStrategy ) ReadFile (path string ) ([]byte , error ) {
96108 key := ss .buildKey (path )
97109
98- result , err := ss .client .GetObject (& s3.GetObjectInput {
110+ result , err := ss .client .GetObject (context . Background (), & s3.GetObjectInput {
99111 Bucket : aws .String (ss .bucketName ),
100112 Key : aws .String (key ),
101113 })
@@ -121,7 +133,7 @@ func (ss *S3StorageStrategy) DeleteFile(path string) error {
121133 }
122134
123135 // 删除单个文件
124- _ , err := ss .client .DeleteObject (& s3.DeleteObjectInput {
136+ _ , err := ss .client .DeleteObject (context . Background (), & s3.DeleteObjectInput {
125137 Bucket : aws .String (ss .bucketName ),
126138 Key : aws .String (key ),
127139 })
@@ -137,7 +149,7 @@ func (ss *S3StorageStrategy) deleteWithPrefix(prefix string) error {
137149 }
138150
139151 // 列出所有匹配的对象
140- result , err := ss .client .ListObjectsV2 (& s3.ListObjectsV2Input {
152+ result , err := ss .client .ListObjectsV2 (context . Background (), & s3.ListObjectsV2Input {
141153 Bucket : aws .String (ss .bucketName ),
142154 Prefix : aws .String (prefix ),
143155 })
@@ -147,7 +159,7 @@ func (ss *S3StorageStrategy) deleteWithPrefix(prefix string) error {
147159
148160 // 删除所有匹配的对象
149161 for _ , obj := range result .Contents {
150- _ , err := ss .client .DeleteObject (& s3.DeleteObjectInput {
162+ _ , err := ss .client .DeleteObject (context . Background (), & s3.DeleteObjectInput {
151163 Bucket : aws .String (ss .bucketName ),
152164 Key : obj .Key ,
153165 })
@@ -163,7 +175,7 @@ func (ss *S3StorageStrategy) deleteWithPrefix(prefix string) error {
163175func (ss * S3StorageStrategy ) FileExists (path string ) bool {
164176 key := ss .buildKey (path )
165177
166- _ , err := ss .client .HeadObject (& s3.HeadObjectInput {
178+ _ , err := ss .client .HeadObject (context . Background (), & s3.HeadObjectInput {
167179 Bucket : aws .String (ss .bucketName ),
168180 Key : aws .String (key ),
169181 })
@@ -213,24 +225,28 @@ func (ss *S3StorageStrategy) GenerateFileURL(filePath string, fileName string) (
213225 return "/share/download" , nil
214226 }
215227
216- // 生成预签名URL
217- req , _ := ss .client .GetObjectRequest (& s3.GetObjectInput {
228+ // 使用AWS SDK v2的预签名客户端
229+ presignClient := s3 .NewPresignClient (ss .client )
230+
231+ // 生成预签名URL(1小时有效期)
232+ presignResult , err := presignClient .PresignGetObject (context .Background (), & s3.GetObjectInput {
218233 Bucket : aws .String (ss .bucketName ),
219234 Key : aws .String (key ),
235+ }, func (opts * s3.PresignOptions ) {
236+ opts .Expires = time .Duration (3600 ) * time .Second
220237 })
221238
222- url , err := req .Presign (3600 ) // 1小时有效期
223239 if err != nil {
224240 return "" , fmt .Errorf ("生成预签名URL失败: %v" , err )
225241 }
226242
227- return url , nil
243+ return presignResult . URL , nil
228244}
229245
230246// TestConnection 测试 S3 连接
231247func (ss * S3StorageStrategy ) TestConnection () error {
232248 // 测试是否可以列出 bucket
233- _ , err := ss .client .HeadBucket (& s3.HeadBucketInput {
249+ _ , err := ss .client .HeadBucket (context . Background (), & s3.HeadBucketInput {
234250 Bucket : aws .String (ss .bucketName ),
235251 })
236252 if err != nil {
@@ -241,7 +257,7 @@ func (ss *S3StorageStrategy) TestConnection() error {
241257 testKey := ss .buildKey (".test_connection" )
242258
243259 // 尝试写入测试文件
244- _ , err = ss .client .PutObject (& s3.PutObjectInput {
260+ _ , err = ss .client .PutObject (context . Background (), & s3.PutObjectInput {
245261 Bucket : aws .String (ss .bucketName ),
246262 Key : aws .String (testKey ),
247263 Body : bytes .NewReader ([]byte ("test" )),
@@ -251,7 +267,7 @@ func (ss *S3StorageStrategy) TestConnection() error {
251267 }
252268
253269 // 清理测试文件
254- _ , err = ss .client .DeleteObject (& s3.DeleteObjectInput {
270+ _ , err = ss .client .DeleteObject (context . Background (), & s3.DeleteObjectInput {
255271 Bucket : aws .String (ss .bucketName ),
256272 Key : aws .String (testKey ),
257273 })
0 commit comments