From 6072d314e1e7893ac8ace57477924bc0ee48c2fb Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 18 Sep 2023 20:41:31 +0100 Subject: [PATCH] b2: fix multipart upload: corrupted on transfer: sizes differ XXX vs 0 Before this change the b2 backend wasn't writing the metadata to the object properly after a multipart upload. The symptom of this was that sometimes it would give the error: corrupted on transfer: sizes differ XXX vs 0 This was fixed by returning the metadata in the chunk writer and setting it in Update. See: https://forum.rclone.org/t/multipart-upload-to-b2-sometimes-failing-with-corrupted-on-transfer-sizes-differ/41829 --- backend/b2/b2.go | 8 ++++++-- backend/b2/upload.go | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/backend/b2/b2.go b/backend/b2/b2.go index f1b0acc31..18c860b62 100644 --- a/backend/b2/b2.go +++ b/backend/b2/b2.go @@ -1930,11 +1930,15 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op return err } } else if size > int64(o.fs.opt.UploadCutoff) { - _, err := multipart.UploadMultipart(ctx, src, in, multipart.UploadMultipartOptions{ + chunkWriter, err := multipart.UploadMultipart(ctx, src, in, multipart.UploadMultipartOptions{ Open: o.fs, OpenOptions: options, }) - return err + if err != nil { + return err + } + up := chunkWriter.(*largeUpload) + return o.decodeMetaDataFileInfo(up.info) } modTime := src.ModTime(ctx) diff --git a/backend/b2/upload.go b/backend/b2/upload.go index c53ecedfb..206c7abe4 100644 --- a/backend/b2/upload.go +++ b/backend/b2/upload.go @@ -85,6 +85,7 @@ type largeUpload struct { uploads []*api.GetUploadPartURLResponse // result of get upload URL calls chunkSize int64 // chunk size to use src *Object // if copying, object we are reading from + info *api.FileInfo // final response with info about the object } // newLargeUpload starts an upload of object o from in with metadata in src @@ -352,7 +353,8 @@ func (up *largeUpload) Close(ctx context.Context) error { if err != nil { return err } - return up.o.decodeMetaDataFileInfo(&response) + up.info = &response + return nil } // Abort aborts the large upload