@@ -54,10 +54,8 @@ func (m *SliceUploadManager) CreateSession(ctx context.Context, storage driver.D
54
54
}
55
55
user := ctx .Value (conf .UserKey ).(* model.User )
56
56
57
- // 生成唯一的TaskID
58
57
taskID := uuid .New ().String ()
59
58
60
- //创建新的上传任务
61
59
createsu := & tables.SliceUpload {
62
60
TaskID : taskID ,
63
61
DstPath : req .Path ,
@@ -121,13 +119,11 @@ func (m *SliceUploadManager) CreateSession(ctx context.Context, storage driver.D
121
119
}, nil
122
120
}
123
121
124
- // getOrLoadSession 获取或加载会话,提高代码复用性
125
122
func (m * SliceUploadManager ) getOrLoadSession (taskID string ) (* SliceUploadSession , error ) {
126
123
session , err , _ := m .sessionG .Do (taskID , func () (* SliceUploadSession , error ) {
127
124
if s , ok := m .cache .Load (taskID ); ok {
128
125
return s .(* SliceUploadSession ), nil
129
126
}
130
- // 首次加载,需要从数据库获取
131
127
su , err := db .GetSliceUploadByTaskID (taskID )
132
128
if err != nil {
133
129
return nil , errors .WithMessagef (err , "failed get slice upload [%s]" , taskID )
@@ -141,21 +137,20 @@ func (m *SliceUploadManager) getOrLoadSession(taskID string) (*SliceUploadSessio
141
137
return session , err
142
138
}
143
139
144
- // UploadSlice 流式上传分片 - 支持流式上传,避免表单上传的内存占用
140
+ // UploadSlice 流式上传分片
145
141
func (m * SliceUploadManager ) UploadSlice (ctx context.Context , storage driver.Driver , req * reqres.UploadSliceReq , reader io.Reader ) error {
146
142
session , err := m .getOrLoadSession (req .TaskID )
147
143
if err != nil {
148
144
log .Errorf ("failed to get session: %+v" , err )
149
145
return err
150
146
}
151
147
152
- // 确保并发安全的错误处理
153
148
defer func () {
154
149
if err != nil {
155
150
session .mutex .Lock ()
156
151
session .Status = tables .SliceUploadStatusFailed
157
152
session .Message = err .Error ()
158
- updateData := * session .SliceUpload // 复制数据避免锁持有时间过长
153
+ updateData := * session .SliceUpload
159
154
session .mutex .Unlock ()
160
155
161
156
if updateErr := db .UpdateSliceUpload (& updateData ); updateErr != nil {
@@ -166,7 +161,6 @@ func (m *SliceUploadManager) UploadSlice(ctx context.Context, storage driver.Dri
166
161
167
162
// 使用锁保护状态检查
168
163
session .mutex .Lock ()
169
- // 检查分片是否已上传过
170
164
if tables .IsSliceUploaded (session .SliceUploadStatus , int (req .SliceNum )) {
171
165
session .mutex .Unlock ()
172
166
log .Warnf ("slice already uploaded,req:%+v" , req )
@@ -178,27 +172,23 @@ func (m *SliceUploadManager) UploadSlice(ctx context.Context, storage driver.Dri
178
172
if req .SliceHash != "" {
179
173
session .mutex .Lock ()
180
174
181
- // 验证分片hash值
182
- if req .SliceNum == 0 { // 第一个分片,slicehash是所有的分片hash
175
+ if req .SliceNum == 0 {
183
176
hs := strings .Split (req .SliceHash , "," )
184
177
if len (hs ) != int (session .SliceCnt ) {
185
178
session .mutex .Unlock ()
186
179
err := fmt .Errorf ("slice hash count mismatch, expected %d, got %d" , session .SliceCnt , len (hs ))
187
180
log .Error ("slice hash count mismatch" , req , err )
188
181
return err
189
182
}
190
- session .SliceHash = req .SliceHash // 存储完整的hash字符串
183
+ session .SliceHash = req .SliceHash
191
184
} else {
192
- // 非第0个分片,不覆盖 SliceHash,保持完整的hash列表
193
185
log .Debugf ("Slice %d hash: %s (keeping complete hash list)" , req .SliceNum , req .SliceHash )
194
186
}
195
187
session .mutex .Unlock ()
196
188
}
197
189
198
- // 根据存储类型处理分片上传
199
190
switch s := storage .(type ) {
200
191
case driver.ISliceUpload :
201
- // Native slice upload: directly pass stream data, let frontend handle retry and recovery
202
192
if err := s .SliceUpload (ctx , session .SliceUpload , req .SliceNum , reader ); err != nil {
203
193
log .Errorf ("Native slice upload failed - TaskID: %s, SliceNum: %d, Error: %v" ,
204
194
req .TaskID , req .SliceNum , err )
@@ -207,13 +197,12 @@ func (m *SliceUploadManager) UploadSlice(ctx context.Context, storage driver.Dri
207
197
log .Debugf ("Native slice upload success - TaskID: %s, SliceNum: %d" ,
208
198
req .TaskID , req .SliceNum )
209
199
210
- default : //其他网盘先缓存到本地
200
+ default :
211
201
if err := session .ensureTmpFile (); err != nil {
212
202
log .Error ("ensureTmpFile error" , req , err )
213
203
return err
214
204
}
215
205
216
- // 流式复制,减少内存占用
217
206
sw := & sliceWriter {
218
207
file : session .tmpFile ,
219
208
offset : int64 (req .SliceNum ) * int64 (session .SliceSize ),
@@ -225,10 +214,9 @@ func (m *SliceUploadManager) UploadSlice(ctx context.Context, storage driver.Dri
225
214
}
226
215
}
227
216
228
- // 原子性更新分片状态
229
217
session .mutex .Lock ()
230
218
tables .SetSliceUploaded (session .SliceUploadStatus , int (req .SliceNum ))
231
- updateData := * session .SliceUpload // 复制数据
219
+ updateData := * session .SliceUpload
232
220
session .mutex .Unlock ()
233
221
234
222
err = db .UpdateSliceUpload (& updateData )
@@ -263,7 +251,6 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
263
251
}
264
252
265
253
defer func () {
266
- // 确保资源清理和缓存删除
267
254
session .cleanup ()
268
255
m .cache .Delete (session .TaskID )
269
256
@@ -278,7 +265,6 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
278
265
log .Errorf ("Failed to update slice upload status: %v" , updateErr )
279
266
}
280
267
} else {
281
- // 上传成功后从数据库中删除记录,允许重复上传
282
268
if deleteErr := db .DeleteSliceUploadByTaskID (session .TaskID ); deleteErr != nil {
283
269
log .Errorf ("Failed to delete slice upload record: %v" , deleteErr )
284
270
}
@@ -293,14 +279,12 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
293
279
return nil , err
294
280
}
295
281
296
- // 原生分片上传成功,直接返回,defer中会删除数据库记录
297
282
return & reqres.UploadSliceCompleteResp {
298
283
Complete : 1 ,
299
284
TaskID : session .TaskID ,
300
285
}, nil
301
286
302
287
default :
303
- // 其他网盘客户端上传到本地后,上传到网盘,使用任务处理
304
288
session .mutex .Lock ()
305
289
tmpFile := session .tmpFile
306
290
session .mutex .Unlock ()
@@ -330,7 +314,6 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
330
314
331
315
if session .AsTask {
332
316
file .SetTmpFile (tmpFile )
333
- // 防止defer中清理文件
334
317
session .mutex .Lock ()
335
318
session .tmpFile = nil
336
319
session .TmpFile = ""
@@ -360,15 +343,12 @@ func (m *SliceUploadManager) CompleteUpload(ctx context.Context, storage driver.
360
343
}
361
344
}
362
345
363
- // ensureTmpFile 确保临时文件存在且正确初始化,线程安全 - 使用持久化目录
364
346
func (s * SliceUploadSession ) ensureTmpFile () error {
365
347
s .mutex .Lock ()
366
348
defer s .mutex .Unlock ()
367
349
368
350
if s .TmpFile == "" {
369
- // 使用TaskID作为文件名的一部分,确保唯一性和可识别性
370
351
filename := fmt .Sprintf ("slice_upload_%s_%s" , s .TaskID , s .Name )
371
- // 清理文件名中的特殊字符
372
352
filename = strings .ReplaceAll (filename , "/" , "_" )
373
353
filename = strings .ReplaceAll (filename , "\\ " , "_" )
374
354
filename = strings .ReplaceAll (filename , ":" , "_" )
@@ -392,7 +372,6 @@ func (s *SliceUploadSession) ensureTmpFile() error {
392
372
// 更新数据库中的临时文件路径
393
373
if updateErr := db .UpdateSliceUpload (s .SliceUpload ); updateErr != nil {
394
374
log .Errorf ("Failed to update temp file path in database: %v" , updateErr )
395
- // 不返回错误,因为文件已经创建成功,只是数据库更新失败
396
375
}
397
376
398
377
log .Debugf ("Created persistent temp file: %s" , tmpPath )
@@ -410,7 +389,6 @@ func (s *SliceUploadSession) ensureTmpFile() error {
410
389
return nil
411
390
}
412
391
413
- // cleanup 清理资源,线程安全 - 保持原始实现
414
392
func (s * SliceUploadSession ) cleanup () {
415
393
s .mutex .Lock ()
416
394
defer s .mutex .Unlock ()
0 commit comments