5
5
"fmt"
6
6
"mime/multipart"
7
7
"os"
8
+ "path/filepath"
8
9
"strings"
9
10
"sync"
10
11
"time"
@@ -18,6 +19,7 @@ import (
18
19
"github.com/OpenListTeam/OpenList/v4/internal/op"
19
20
"github.com/OpenListTeam/OpenList/v4/internal/stream"
20
21
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
22
+ "github.com/OpenListTeam/OpenList/v4/pkg/tempdir"
21
23
"github.com/google/uuid"
22
24
"github.com/pkg/errors"
23
25
"gorm.io/gorm"
@@ -39,12 +41,9 @@ type SliceUploadSession struct {
39
41
40
42
// NewSliceUploadManager 创建分片上传管理器
41
43
func NewSliceUploadManager () * SliceUploadManager {
42
- tempDir := os .TempDir () // 默认使用系统临时目录
43
- if conf .Conf != nil && conf .Conf .TempDir != "" {
44
- tempDir = conf .Conf .TempDir
45
- }
44
+ tempDirPath := tempdir .GetPersistentTempDir ()
46
45
return & SliceUploadManager {
47
- tempDir : tempDir ,
46
+ tempDir : tempDirPath ,
48
47
}
49
48
}
50
49
@@ -74,14 +73,40 @@ func (m *SliceUploadManager) CreateSession(ctx context.Context, storage driver.D
74
73
}
75
74
76
75
if su .ID != 0 { // 找到未完成的上传任务,支持断点续传
77
- session := & SliceUploadSession {SliceUpload : su }
78
- m .cache .Store (su .TaskID , session )
79
- return & reqres.PreupResp {
80
- TaskID : su .TaskID ,
81
- SliceSize : su .SliceSize ,
82
- SliceCnt : su .SliceCnt ,
83
- SliceUploadStatus : su .SliceUploadStatus ,
84
- }, nil
76
+ // 验证临时文件是否仍然存在(重启后可能被清理)
77
+ if su .TmpFile != "" {
78
+ if _ , err := os .Stat (su .TmpFile ); os .IsNotExist (err ) {
79
+ // 临时文件丢失,清理数据库记录,重新开始
80
+ log .Warnf ("Temporary file lost after restart, cleaning up task: %s" , su .TaskID )
81
+ if deleteErr := db .DeleteSliceUploadByTaskID (su .TaskID ); deleteErr != nil {
82
+ log .Errorf ("Failed to delete lost slice upload task: %v" , deleteErr )
83
+ }
84
+ // 继续创建新任务
85
+ } else {
86
+ // 临时文件存在,可以继续断点续传
87
+ session := & SliceUploadSession {SliceUpload : su }
88
+ m .cache .Store (su .TaskID , session )
89
+ log .Infof ("Resuming slice upload after restart: %s, completed slices: %d/%d" ,
90
+ su .TaskID , tables .CountUploadedSlices (su .SliceUploadStatus ), su .SliceCnt )
91
+ return & reqres.PreupResp {
92
+ TaskID : su .TaskID ,
93
+ SliceSize : su .SliceSize ,
94
+ SliceCnt : su .SliceCnt ,
95
+ SliceUploadStatus : su .SliceUploadStatus ,
96
+ }, nil
97
+ }
98
+ } else {
99
+ // 原生分片上传(如123open/baidu),无需临时文件
100
+ session := & SliceUploadSession {SliceUpload : su }
101
+ m .cache .Store (su .TaskID , session )
102
+ log .Infof ("Resuming native slice upload after restart: %s" , su .TaskID )
103
+ return & reqres.PreupResp {
104
+ TaskID : su .TaskID ,
105
+ SliceSize : su .SliceSize ,
106
+ SliceCnt : su .SliceCnt ,
107
+ SliceUploadStatus : su .SliceUploadStatus ,
108
+ }, nil
109
+ }
85
110
}
86
111
87
112
srcobj , err := op .Get (ctx , storage , actualPath )
@@ -419,39 +444,48 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
419
444
}
420
445
}
421
446
422
- // ensureTmpFile 确保临时文件存在且正确初始化,线程安全 - 保持原始实现
447
+ // ensureTmpFile 确保临时文件存在且正确初始化,线程安全 - 使用持久化目录
423
448
func (s * SliceUploadSession ) ensureTmpFile () error {
424
449
s .mutex .Lock ()
425
450
defer s .mutex .Unlock ()
426
451
427
452
if s .TmpFile == "" {
428
- tempDir := os .TempDir () // 默认使用系统临时目录
429
- if conf .Conf != nil && conf .Conf .TempDir != "" {
430
- tempDir = conf .Conf .TempDir
431
- }
432
- tf , err := os .CreateTemp (tempDir , "file-*" )
453
+ tempDirPath := tempdir .GetPersistentTempDir ()
454
+
455
+ // 使用TaskID作为文件名的一部分,确保唯一性和可识别性
456
+ filename := fmt .Sprintf ("slice_upload_%s_%s" , s .TaskID , s .Name )
457
+ // 清理文件名中的特殊字符
458
+ filename = strings .ReplaceAll (filename , "/" , "_" )
459
+ filename = strings .ReplaceAll (filename , "\\ " , "_" )
460
+ filename = strings .ReplaceAll (filename , ":" , "_" )
461
+
462
+ tmpPath := filepath .Join (tempDirPath , filename )
463
+
464
+ tf , err := os .OpenFile (tmpPath , os .O_CREATE | os .O_RDWR , 0644 )
433
465
if err != nil {
434
- return fmt .Errorf ("CreateTemp error: %w" , err )
466
+ return fmt .Errorf ("create persistent temp file error: %w" , err )
435
467
}
436
468
437
- abspath := tf .Name () //这里返回的是绝对路径
438
- if err = os .Truncate (abspath , int64 (s .Size )); err != nil {
469
+ if err = os .Truncate (tmpPath , int64 (s .Size )); err != nil {
439
470
tf .Close () // 确保文件被关闭
440
- os .Remove (abspath ) // 清理文件
441
- return fmt .Errorf ("Truncate error: %w" , err )
471
+ os .Remove (tmpPath ) // 清理文件
472
+ return fmt .Errorf ("truncate persistent temp file error: %w" , err )
442
473
}
443
474
444
- s .TmpFile = abspath
475
+ s .TmpFile = tmpPath
445
476
s .tmpFile = tf
477
+
478
+ log .Debugf ("Created persistent temp file: %s" , tmpPath )
446
479
return nil
447
480
}
448
481
449
482
if s .tmpFile == nil {
450
483
var err error
451
484
s .tmpFile , err = os .OpenFile (s .TmpFile , os .O_RDWR , 0644 )
452
485
if err != nil {
453
- return fmt .Errorf ("OpenFile error: %w" , err )
486
+ return fmt .Errorf ("reopen persistent temp file error: %w" , err )
454
487
}
488
+ log .Debugf ("Reopened persistent temp file: %s" , s .TmpFile )
455
489
}
456
490
return nil
457
491
}
0 commit comments