s3: multipart upload verifies uploaded parts
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
package s3api
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/chrislusf/seaweedfs/weed/glog"
|
||||
xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
|
||||
"github.com/chrislusf/seaweedfs/weed/s3api/s3err"
|
||||
weed_server "github.com/chrislusf/seaweedfs/weed/server"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -56,8 +58,16 @@ func (s3a *S3ApiServer) NewMultipartUploadHandler(w http.ResponseWriter, r *http
|
||||
|
||||
// CompleteMultipartUploadHandler - Completes multipart upload.
|
||||
func (s3a *S3ApiServer) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html
|
||||
|
||||
bucket, object := xhttp.GetBucketAndObject(r)
|
||||
|
||||
parts := &CompleteMultipartUpload{}
|
||||
if err := xmlDecoder(r.Body, parts, r.ContentLength); err != nil {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrMalformedXML)
|
||||
return
|
||||
}
|
||||
|
||||
// Get upload id.
|
||||
uploadID, _, _, _ := getObjectResources(r.URL.Query())
|
||||
|
||||
@@ -65,7 +75,7 @@ func (s3a *S3ApiServer) CompleteMultipartUploadHandler(w http.ResponseWriter, r
|
||||
Bucket: aws.String(bucket),
|
||||
Key: objectKey(aws.String(object)),
|
||||
UploadId: aws.String(uploadID),
|
||||
})
|
||||
}, parts)
|
||||
|
||||
glog.V(2).Info("CompleteMultipartUploadHandler", string(s3err.EncodeXMLResponse(response)), errCode)
|
||||
|
||||
@@ -268,8 +278,24 @@ func getObjectResources(values url.Values) (uploadID string, partNumberMarker, m
|
||||
return
|
||||
}
|
||||
|
||||
type byCompletedPartNumber []*s3.CompletedPart
|
||||
func xmlDecoder(body io.Reader, v interface{}, size int64) error {
|
||||
var lbody io.Reader
|
||||
if size > 0 {
|
||||
lbody = io.LimitReader(body, size)
|
||||
} else {
|
||||
lbody = body
|
||||
}
|
||||
d := xml.NewDecoder(lbody)
|
||||
d.CharsetReader = func(label string, input io.Reader) (io.Reader, error) {
|
||||
return input, nil
|
||||
}
|
||||
return d.Decode(v)
|
||||
}
|
||||
|
||||
func (a byCompletedPartNumber) Len() int { return len(a) }
|
||||
func (a byCompletedPartNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byCompletedPartNumber) Less(i, j int) bool { return *a[i].PartNumber < *a[j].PartNumber }
|
||||
type CompleteMultipartUpload struct {
|
||||
Parts []CompletedPart `xml:"Part"`
|
||||
}
|
||||
type CompletedPart struct {
|
||||
ETag string
|
||||
PartNumber int
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user