|
|
@ -5,6 +5,7 @@ import ( |
|
|
|
"fmt" |
|
|
|
"github.com/chrislusf/seaweedfs/weed/s3api/s3err" |
|
|
|
"path/filepath" |
|
|
|
"sort" |
|
|
|
"strconv" |
|
|
|
"strings" |
|
|
|
"time" |
|
|
@ -62,10 +63,15 @@ type CompleteMultipartUploadResult struct { |
|
|
|
s3.CompleteMultipartUploadOutput |
|
|
|
} |
|
|
|
|
|
|
|
func (s3a *S3ApiServer) completeMultipartUpload(input *s3.CompleteMultipartUploadInput) (output *CompleteMultipartUploadResult, code s3err.ErrorCode) { |
|
|
|
func (s3a *S3ApiServer) completeMultipartUpload(input *s3.CompleteMultipartUploadInput, parts *CompleteMultipartUpload) (output *CompleteMultipartUploadResult, code s3err.ErrorCode) { |
|
|
|
|
|
|
|
glog.V(2).Infof("completeMultipartUpload input %v", input) |
|
|
|
|
|
|
|
completedParts := parts.Parts |
|
|
|
sort.Slice(completedParts, func(i, j int) bool { |
|
|
|
return completedParts[i].PartNumber < completedParts[j].PartNumber |
|
|
|
}) |
|
|
|
|
|
|
|
uploadDirectory := s3a.genUploadsFolder(*input.Bucket) + "/" + *input.UploadId |
|
|
|
|
|
|
|
entries, _, err := s3a.list(uploadDirectory, "", "", false, maxPartsList) |
|
|
@ -80,14 +86,16 @@ func (s3a *S3ApiServer) completeMultipartUpload(input *s3.CompleteMultipartUploa |
|
|
|
return nil, s3err.ErrNoSuchUpload |
|
|
|
} |
|
|
|
|
|
|
|
mime := pentry.Attributes.Mime |
|
|
|
|
|
|
|
var finalParts []*filer_pb.FileChunk |
|
|
|
var offset int64 |
|
|
|
var mime string |
|
|
|
|
|
|
|
for _, entry := range entries { |
|
|
|
if strings.HasSuffix(entry.Name, ".part") && !entry.IsDirectory { |
|
|
|
if entry.Name == "0001.part" && entry.Attributes.Mime != "" { |
|
|
|
mime = entry.Attributes.Mime |
|
|
|
_, found := findByPartNumber(entry.Name, completedParts) |
|
|
|
if !found { |
|
|
|
continue |
|
|
|
} |
|
|
|
for _, chunk := range entry.Chunks { |
|
|
|
p := &filer_pb.FileChunk{ |
|
|
@ -156,6 +164,20 @@ func (s3a *S3ApiServer) completeMultipartUpload(input *s3.CompleteMultipartUploa |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func findByPartNumber(fileName string, parts []CompletedPart) (etag string, found bool) { |
|
|
|
partNumber, formatErr := strconv.Atoi(fileName[:4]) |
|
|
|
if formatErr != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
x := sort.Search(len(parts), func(i int) bool { |
|
|
|
return parts[i].PartNumber >= partNumber |
|
|
|
}) |
|
|
|
if parts[x].PartNumber != partNumber { |
|
|
|
return |
|
|
|
} |
|
|
|
return parts[x].ETag, true |
|
|
|
} |
|
|
|
|
|
|
|
func (s3a *S3ApiServer) abortMultipartUpload(input *s3.AbortMultipartUploadInput) (output *s3.AbortMultipartUploadOutput, code s3err.ErrorCode) { |
|
|
|
|
|
|
|
glog.V(2).Infof("abortMultipartUpload input %v", input) |
|
|
|