@@ -5,31 +5,18 @@ package storage
55import (
66 "context"
77 "fmt"
8- "log"
98 "os"
109 "strings"
1110 "time"
1211
1312 "github.com/aws/aws-sdk-go/aws"
14- "github.com/aws/aws-sdk-go/aws/awserr"
1513 "github.com/aws/aws-sdk-go/aws/credentials"
1614 "github.com/aws/aws-sdk-go/aws/session"
1715 "github.com/aws/aws-sdk-go/service/s3"
1816 "github.com/aws/aws-sdk-go/service/s3/s3manager"
1917 "m7s.live/v5/pkg/config"
2018)
2119
22- // isS3NotFoundError 使用 AWS SDK 类型断言判断是否为 404 错误,避免脆弱的字符串匹配
23- func isS3NotFoundError (err error ) bool {
24- if aerr , ok := err .(awserr.Error ); ok {
25- switch aerr .Code () {
26- case s3 .ErrCodeNoSuchKey , "NotFound" , "NoSuchBucket" :
27- return true
28- }
29- }
30- return false
31- }
32-
3320// S3StorageConfig S3存储配置
3421type S3StorageConfig struct {
3522 Endpoint string `desc:"S3服务端点"`
@@ -159,7 +146,8 @@ func (s *S3Storage) Exists(ctx context.Context, path string) (bool, error) {
159146 })
160147
161148 if err != nil {
162- if isS3NotFoundError (err ) {
149+ // 检查是否是404错误
150+ if strings .Contains (err .Error (), "NotFound" ) || strings .Contains (err .Error (), "NoSuchKey" ) {
163151 return false , nil
164152 }
165153 return false , err
@@ -177,7 +165,7 @@ func (s *S3Storage) GetSize(ctx context.Context, path string) (int64, error) {
177165 })
178166
179167 if err != nil {
180- if isS3NotFoundError (err ) {
168+ if strings . Contains (err . Error (), "NotFound" ) || strings . Contains ( err . Error (), "NoSuchKey" ) {
181169 return 0 , ErrFileNotFound
182170 }
183171 return 0 , err
@@ -336,13 +324,20 @@ func (w *S3File) Sync() error {
336324 return nil
337325 }
338326
339- // 先将临时文件同步到磁盘
327+ // 如果使用临时文件,先同步到磁盘
340328 if w .tempFile != nil {
341329 if err := w .tempFile .Sync (); err != nil {
342330 return err
343331 }
332+ // 获取文件大小用于日志
333+ if stat , err := w .tempFile .Stat (); err == nil {
334+ fmt .Printf ("[S3File.Sync] tempFile size: %d bytes, path: %s\n " , stat .Size (), w .filePath )
335+ }
336+ }
337+ if err := w .uploadTempFile (); err != nil {
338+ return err
344339 }
345- return w . uploadTempFile ()
340+ return nil
346341}
347342
348343func (w * S3File ) Seek (offset int64 , whence int ) (int64 , error ) {
@@ -358,18 +353,17 @@ func (w *S3File) Seek(offset int64, whence int) (int64, error) {
358353}
359354
360355func (w * S3File ) Close () error {
361- // 用 defer 确保无论上传成功与否,临时文件句柄和磁盘文件都被清理
362- defer func () {
363- if w .tempFile != nil {
364- w .tempFile .Close ()
365- w .tempFile = nil
366- }
367- if w .filePath != "" {
368- os .Remove (w .filePath )
369- w .filePath = ""
370- }
371- }()
372- return w .Sync ()
356+ if err := w .Sync (); err != nil {
357+ return err
358+ }
359+ if w .tempFile != nil {
360+ w .tempFile .Close ()
361+ }
362+ // 清理临时文件
363+ if w .filePath != "" {
364+ os .Remove (w .filePath )
365+ }
366+ return nil
373367}
374368
375369// createTempFile 创建临时文件
@@ -385,30 +379,23 @@ func (w *S3File) createTempFile() error {
385379}
386380
387381func (w * S3File ) Stat () (os.FileInfo , error ) {
388- if w .tempFile == nil {
389- return nil , fmt .Errorf ("s3 file not initialized" )
390- }
391382 return w .tempFile .Stat ()
392383}
393384
394385// uploadTempFile 上传临时文件到S3
395386func (w * S3File ) uploadTempFile () (err error ) {
396387 // 重置文件指针到开头
397- if _ , err = w .tempFile .Seek (0 , 0 ); err != nil {
388+ if _ , err := w .tempFile .Seek (0 , 0 ); err != nil {
389+ fmt .Printf ("[S3File.uploadTempFile] failed to seek: %v\n " , err )
398390 return fmt .Errorf ("failed to seek temp file: %w" , err )
399391 }
400392
393+ // 获取文件大小
401394 stat , _ := w .tempFile .Stat ()
402- log .Printf ("[S3] uploading: bucket=%s key=%s size=%d" , w .storage .config .Bucket , w .objectKey , stat .Size ())
403-
404- // 使用带超时的 background context,避免因录像 context 取消而中断上传
405- timeout := w .storage .config .Timeout
406- if timeout <= 0 {
407- timeout = 30 * time .Second
408- }
409- ctx , cancel := context .WithTimeout (context .Background (), timeout )
410- defer cancel ()
395+ fmt .Printf ("[S3File.uploadTempFile] uploading to S3: bucket=%s, key=%s, size=%d\n " ,
396+ w .storage .config .Bucket , w .objectKey , stat .Size ())
411397
398+ // 构建上传请求,携带用户自定义元数据
412399 uploadInput := & s3manager.UploadInput {
413400 Bucket : aws .String (w .storage .config .Bucket ),
414401 Key : aws .String (w .objectKey ),
@@ -418,17 +405,21 @@ func (w *S3File) uploadTempFile() (err error) {
418405 if len (w .metadata ) > 0 {
419406 uploadInput .Metadata = aws .StringMap (w .metadata )
420407 }
408+ // 上传到S3
409+ _ , err = w .storage .uploader .UploadWithContext (w .ctx , uploadInput )
421410
422- if _ , err = w .storage .uploader .UploadWithContext (ctx , uploadInput ); err != nil {
411+ if err != nil {
412+ fmt .Printf ("[S3File.uploadTempFile] upload failed: %v\n " , err )
423413 return fmt .Errorf ("failed to upload to S3: %w" , err )
424414 }
425415
426- log .Printf ("[S3 ] upload successful: %s" , w .objectKey )
416+ fmt .Printf ("[S3File.uploadTempFile ] upload successful: %s\n " , w .objectKey )
427417 return nil
428418}
429419
430420// downloadToTemp 下载S3对象到本地临时文件
431421func (w * S3File ) downloadToTemp () error {
422+ // 创建临时文件
432423 tempFile , err := os .CreateTemp ("" , "s3reader_*.tmp" )
433424 if err != nil {
434425 return fmt .Errorf ("failed to create temp file: %w" , err )
@@ -437,6 +428,7 @@ func (w *S3File) downloadToTemp() error {
437428 w .tempFile = tempFile
438429 w .filePath = tempFile .Name ()
439430
431+ // 下载S3对象
440432 _ , err = w .storage .downloader .DownloadWithContext (w .ctx , tempFile , & s3.GetObjectInput {
441433 Bucket : aws .String (w .storage .config .Bucket ),
442434 Key : aws .String (w .objectKey ),
@@ -445,14 +437,15 @@ func (w *S3File) downloadToTemp() error {
445437 if err != nil {
446438 tempFile .Close ()
447439 os .Remove (w .filePath )
448- if isS3NotFoundError (err ) {
440+ if strings . Contains (err . Error (), "NotFound" ) || strings . Contains ( err . Error (), "NoSuchKey" ) {
449441 return ErrFileNotFound
450442 }
451443 return fmt .Errorf ("failed to download from S3: %w" , err )
452444 }
453445
454446 // 重置文件指针到开始位置
455- if _ , err = tempFile .Seek (0 , 0 ); err != nil {
447+ _ , err = tempFile .Seek (0 , 0 )
448+ if err != nil {
456449 tempFile .Close ()
457450 os .Remove (w .filePath )
458451 return fmt .Errorf ("failed to seek temp file: %w" , err )
0 commit comments