diff --git a/api/object.go b/api/object.go index 7141f54f5..80b24d341 100644 --- a/api/object.go +++ b/api/object.go @@ -196,11 +196,13 @@ type ( ContractSet string MimeType string DisablePreshardingEncryption bool + ContentLength int64 } UploadMultipartUploadPartOptions struct { DisablePreshardingEncryption bool EncryptionOffset int + ContentLength int64 } ) diff --git a/s3/backend.go b/s3/backend.go index 9f6c8beef..83f59c637 100644 --- a/s3/backend.go +++ b/s3/backend.go @@ -337,7 +337,9 @@ func (s *s3) DeleteObject(ctx context.Context, bucketName, objectName string) (g // TODO: Metadata is currently ignored. The backend requires an update to // support it. func (s *s3) PutObject(ctx context.Context, bucketName, key string, meta map[string]string, input io.Reader, size int64) (gofakes3.PutObjectResult, error) { - opts := api.UploadObjectOptions{} + opts := api.UploadObjectOptions{ + ContentLength: size, + } if ct, ok := meta["Content-Type"]; ok { opts.MimeType = ct } @@ -403,6 +405,7 @@ func (s *s3) CreateMultipartUpload(ctx context.Context, bucket, key string, meta func (s *s3) UploadPart(ctx context.Context, bucket, object string, id gofakes3.UploadID, partNumber int, contentLength int64, input io.Reader) (*gofakes3.UploadPartResult, error) { res, err := s.w.UploadMultipartUploadPart(ctx, input, bucket, object, string(id), partNumber, api.UploadMultipartUploadPartOptions{ DisablePreshardingEncryption: true, + ContentLength: contentLength, }) if err != nil { return nil, gofakes3.ErrorMessage(gofakes3.ErrInternal, err.Error()) diff --git a/worker/client/client.go b/worker/client/client.go index 048ce225c..f275bcdaf 100644 --- a/worker/client/client.go +++ b/worker/client/client.go @@ -194,6 +194,21 @@ func (c *Client) UploadMultipartUploadPart(ctx context.Context, r io.Reader, buc panic(err) } req.SetBasicAuth("", c.c.WithContext(ctx).Password) + if opts.ContentLength != 0 { + req.ContentLength = opts.ContentLength + } else { + if s, ok := r.(io.Seeker); ok { + length, err := s.Seek(0, io.SeekEnd) + if err != nil { + return nil, err + } + _, err = s.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } + req.ContentLength = length + } + } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err @@ -225,6 +240,21 @@ func (c *Client) UploadObject(ctx context.Context, r io.Reader, bucket, path str panic(err) } req.SetBasicAuth("", c.c.WithContext(ctx).Password) + if opts.ContentLength != 0 { + req.ContentLength = opts.ContentLength + } else { + if s, ok := r.(io.Seeker); ok { + length, err := s.Seek(0, io.SeekEnd) + if err != nil { + return nil, err + } + _, err = s.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } + req.ContentLength = length + } + } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err