mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2026-10-10 13:03:09 +08:00
fix(drivers/189pc): preserve file extension during family transfer (#3083)
* fix(189pc): preserve family transfer extension - Preserve the source extension in family-transfer temporary upload names. - Fall back to .transfer for extensionless source files. - Add unit coverage for extension handling. Co-authored-by: Codex <267193182+codex@users.noreply.github.com> * fix(189pc): include extension in upload progress key - Separate resumable upload state for identical content with different extensions. - Preserve resume behavior when only the temporary file name changes. - Add unit coverage for both cases. Co-authored-by: Codex <267193182+codex@users.noreply.github.com> --------- Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
This commit is contained in:
+10
-1
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -366,6 +367,14 @@ func (y *Cloud189PC) Remove(ctx context.Context, obj model.Obj) error {
|
||||
return y.WaitBatchTask("DELETE", resp.TaskID, time.Millisecond*200)
|
||||
}
|
||||
|
||||
func familyTransferTempName(srcName string) string {
|
||||
ext := path.Ext(srcName)
|
||||
if ext == "" {
|
||||
ext = ".transfer"
|
||||
}
|
||||
return fmt.Sprintf("0%s%s", uuid.NewString(), ext)
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (newObj model.Obj, err error) {
|
||||
overwrite := true
|
||||
isFamily := y.isFamily()
|
||||
@@ -399,7 +408,7 @@ func (y *Cloud189PC) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
||||
srcName := stream.GetName()
|
||||
stream = &WrapFileStreamer{
|
||||
FileStreamer: stream,
|
||||
Name: fmt.Sprintf("0%s.transfer", uuid.NewString()),
|
||||
Name: familyTransferTempName(srcName),
|
||||
}
|
||||
|
||||
// 使用家庭云上传
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package _189pc
|
||||
|
||||
import (
|
||||
"path"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFamilyTransferTempNamePreservesExtension(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want string
|
||||
}{
|
||||
{name: "photo.jpg", want: ".jpg"},
|
||||
{name: "PHOTO.PNG", want: ".PNG"},
|
||||
{name: "archive.tar.gz", want: ".gz"},
|
||||
{name: "no-extension", want: ".transfer"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := familyTransferTempName(tt.name)
|
||||
if !strings.HasPrefix(got, "0") {
|
||||
t.Fatalf("temporary name %q must start with 0", got)
|
||||
}
|
||||
if ext := path.Ext(got); ext != tt.want {
|
||||
t.Fatalf("temporary name extension = %q, want %q", ext, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadProgressKeysIncludeExtension(t *testing.T) {
|
||||
jpgKeys := uploadProgressKeys("session", "same-md5", "photo.jpg")
|
||||
txtKeys := uploadProgressKeys("session", "same-md5", "photo.txt")
|
||||
retryKeys := uploadProgressKeys("session", "same-md5", "different-name.jpg")
|
||||
|
||||
if slices.Equal(jpgKeys, txtKeys) {
|
||||
t.Fatal("files with different extensions must not share upload progress")
|
||||
}
|
||||
if !slices.Equal(jpgKeys, retryKeys) {
|
||||
t.Fatal("files with the same session, MD5, and extension should share upload progress")
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -1203,6 +1204,10 @@ func (y *Cloud189PC) FastUpload(ctx context.Context, dstDir model.Obj, file mode
|
||||
return y.fastUpload(ctx, dstDir, file, up, isFamily, overwrite, generateTorrent)
|
||||
}
|
||||
|
||||
func uploadProgressKeys(sessionKey, fileMD5, fileName string) []string {
|
||||
return []string{sessionKey, fileMD5, path.Ext(fileName)}
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) fastUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress, isFamily bool, overwrite bool, generateTorrent bool) (model.Obj, error) {
|
||||
var (
|
||||
cache = file.GetFile()
|
||||
@@ -1305,7 +1310,8 @@ func (y *Cloud189PC) fastUpload(ctx context.Context, dstDir model.Obj, file mode
|
||||
}
|
||||
|
||||
// 尝试恢复进度
|
||||
uploadProgress, ok := base.GetUploadProgress[*UploadProgress](y, y.getTokenInfo().SessionKey, fileMd5Hex)
|
||||
progressKeys := uploadProgressKeys(y.getTokenInfo().SessionKey, fileMd5Hex, file.GetName())
|
||||
uploadProgress, ok := base.GetUploadProgress[*UploadProgress](y, progressKeys...)
|
||||
if !ok {
|
||||
// step.2 预上传
|
||||
params := Params{
|
||||
@@ -1373,7 +1379,7 @@ func (y *Cloud189PC) fastUpload(ctx context.Context, dstDir model.Obj, file mode
|
||||
if err = threadG.Wait(); err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
uploadProgress.UploadParts = utils.SliceFilter(uploadProgress.UploadParts, func(s string) bool { return s != "" })
|
||||
base.SaveUploadProgress(y, uploadProgress, y.getTokenInfo().SessionKey, fileMd5Hex)
|
||||
base.SaveUploadProgress(y, uploadProgress, progressKeys...)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user