11package teldrive
22
33import (
4+ "crypto/md5"
5+ "encoding/hex"
46 "fmt"
57 "io"
68 "net/http"
@@ -16,6 +18,7 @@ import (
1618 "github.com/OpenListTeam/OpenList/v4/pkg/utils"
1719 "github.com/avast/retry-go"
1820 "github.com/go-resty/resty/v2"
21+ "github.com/google/uuid"
1922 "github.com/pkg/errors"
2023 "golang.org/x/net/context"
2124 "golang.org/x/sync/errgroup"
@@ -38,6 +41,11 @@ func (d *Teldrive) touch(name, path string) error {
3841 return nil
3942}
4043
44+ func getMD5Hash (text string ) string {
45+ hash := md5 .Sum ([]byte (text ))
46+ return hex .EncodeToString (hash [:])
47+ }
48+
4149func (d * Teldrive ) createFileOnUploadSuccess (name , id , path string , uploadedFileParts []FilePart , totalSize int64 ) error {
4250 remoteFileParts , err := d .getFilePart (id )
4351 if err != nil {
@@ -101,12 +109,10 @@ func (d *Teldrive) getFilePart(fileId string) ([]FilePart, error) {
101109 return uploadedParts , nil
102110}
103111
104- func (d * Teldrive ) singleUploadRequest (fileId string , callback base.ReqCallback , resp interface {} ) error {
112+ func (d * Teldrive ) singleUploadRequest (ctx context. Context , fileId string , callback base.ReqCallback , resp any ) error {
105113 url := d .Address + "/api/uploads/" + fileId
106114 client := resty .New ().SetTimeout (0 )
107115
108- ctx := context .Background ()
109-
110116 req := client .R ().
111117 SetContext (ctx )
112118 req .SetHeader ("Cookie" , d .Cookie )
@@ -135,16 +141,18 @@ func (d *Teldrive) singleUploadRequest(fileId string, callback base.ReqCallback,
135141}
136142
137143func (d * Teldrive ) doSingleUpload (ctx context.Context , dstDir model.Obj , file model.FileStreamer , up model.UpdateProgress ,
138- totalParts int , chunkSize int64 , fileId string ) error {
144+ maxRetried , totalParts int , chunkSize int64 , fileId string ) error {
139145
140146 totalSize := file .GetSize ()
141147 var fileParts []FilePart
142148 var uploaded int64 = 0
143- ss , err := stream .NewStreamSectionReader (file , int (totalSize ), & up )
149+ var partName string
150+ chunkSize = min (totalSize , chunkSize )
151+ ss , err := stream .NewStreamSectionReader (file , int (chunkSize ), & up )
144152 if err != nil {
145153 return err
146154 }
147-
155+ chunkCnt := 0
148156 for uploaded < totalSize {
149157 if utils .IsCanceled (ctx ) {
150158 return ctx .Err ()
@@ -154,20 +162,27 @@ func (d *Teldrive) doSingleUpload(ctx context.Context, dstDir model.Obj, file mo
154162 if err != nil {
155163 return err
156164 }
165+ chunkCnt += 1
157166 filePart := & FilePart {}
158167 if err := retry .Do (func () error {
159168
160169 if _ , err := rd .Seek (0 , io .SeekStart ); err != nil {
161170 return err
162171 }
163172
164- if err := d .singleUploadRequest (fileId , func (req * resty.Request ) {
173+ if d .RandomChunkName {
174+ partName = getMD5Hash (uuid .New ().String ())
175+ } else {
176+ partName = file .GetName ()
177+ if totalParts > 1 {
178+ partName = fmt .Sprintf ("%s.part.%03d" , file .GetName (), chunkCnt )
179+ }
180+ }
181+
182+ if err := d .singleUploadRequest (ctx , fileId , func (req * resty.Request ) {
165183 uploadParams := map [string ]string {
166- "partName" : func () string {
167- digits := len (strconv .Itoa (totalParts ))
168- return file .GetName () + fmt .Sprintf (".%0*d" , digits , 1 )
169- }(),
170- "partNo" : strconv .Itoa (1 ),
184+ "partName" : partName ,
185+ "partNo" : strconv .Itoa (chunkCnt ),
171186 "fileName" : file .GetName (),
172187 }
173188 req .SetQueryParams (uploadParams )
@@ -180,7 +195,7 @@ func (d *Teldrive) doSingleUpload(ctx context.Context, dstDir model.Obj, file mo
180195 return nil
181196 },
182197 retry .Context (ctx ),
183- retry .Attempts (3 ),
198+ retry .Attempts (uint ( maxRetried ) ),
184199 retry .DelayType (retry .BackOffDelay ),
185200 retry .Delay (time .Second )); err != nil {
186201 return err
@@ -189,8 +204,11 @@ func (d *Teldrive) doSingleUpload(ctx context.Context, dstDir model.Obj, file mo
189204 if filePart .Name != "" {
190205 fileParts = append (fileParts , * filePart )
191206 uploaded += curChunkSize
192- up (float64 (uploaded ) / float64 (totalSize ))
207+ up (float64 (uploaded ) / float64 (totalSize ) * 100 )
193208 ss .FreeSectionReader (rd )
209+ } else {
210+ // For common situation this code won't reach
211+ return fmt .Errorf ("[Teldrive] upload chunk %d failed: filePart Somehow missing" , chunkCnt )
194212 }
195213
196214 }
@@ -318,6 +336,7 @@ func (d *Teldrive) doMultiUpload(ctx context.Context, dstDir model.Obj, file mod
318336func (d * Teldrive ) uploadSingleChunk (ctx context.Context , fileId string , task chunkTask , totalParts , maxRetried int ) (* FilePart , error ) {
319337 filePart := & FilePart {}
320338 retryCount := 0
339+ var partName string
321340 defer task .ss .FreeSectionReader (task .reader )
322341
323342 for {
@@ -331,12 +350,22 @@ func (d *Teldrive) uploadSingleChunk(ctx context.Context, fileId string, task ch
331350 return & existingPart , nil
332351 }
333352
334- err := d .singleUploadRequest (fileId , func (req * resty.Request ) {
353+ if _ , err := task .reader .Seek (0 , io .SeekStart ); err != nil {
354+ return nil , err
355+ }
356+
357+ if d .RandomChunkName {
358+ partName = getMD5Hash (uuid .New ().String ())
359+ } else {
360+ partName = task .fileName
361+ if totalParts > 1 {
362+ partName = fmt .Sprintf ("%s.part.%03d" , task .fileName , task .chunkIdx )
363+ }
364+ }
365+
366+ err := d .singleUploadRequest (ctx , fileId , func (req * resty.Request ) {
335367 uploadParams := map [string ]string {
336- "partName" : func () string {
337- digits := len (strconv .Itoa (totalParts ))
338- return task .fileName + fmt .Sprintf (".%0*d" , digits , task .chunkIdx )
339- }(),
368+ "partName" : partName ,
340369 "partNo" : strconv .Itoa (task .chunkIdx ),
341370 "fileName" : task .fileName ,
342371 }
0 commit comments