mirror of
https://github.com/minio/minio.git
synced 2025-04-22 03:24:38 -04:00
Multipart: Minimum part size limit does not apply to the last part during CompleteMultipartUpload. (#1518) (#1538)
This commit is contained in:
parent
90ea494338
commit
04a5b25929
@ -73,10 +73,22 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all parts, validate them and then commit to disk.
|
// Loop through all parts, validate them and then commit to disk.
|
||||||
for _, part := range parts {
|
for i, part := range parts {
|
||||||
// Construct part suffix.
|
// Construct part suffix.
|
||||||
partSuffix := fmt.Sprintf("%.5d.%s", part.PartNumber, part.ETag)
|
partSuffix := fmt.Sprintf("%.5d.%s", part.PartNumber, part.ETag)
|
||||||
multipartPartFile := path.Join(mpartMetaPrefix, bucket, object, uploadID, partSuffix)
|
multipartPartFile := path.Join(mpartMetaPrefix, bucket, object, uploadID, partSuffix)
|
||||||
|
var fi FileInfo
|
||||||
|
fi, err = fs.storage.StatFile(minioMetaBucket, multipartPartFile)
|
||||||
|
if err != nil {
|
||||||
|
if err == errFileNotFound {
|
||||||
|
return "", InvalidPart{}
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// All parts except the last part has to be atleast 5MB.
|
||||||
|
if (i < len(parts)-1) && !isMinAllowedPartSize(fi.Size) {
|
||||||
|
return "", PartTooSmall{}
|
||||||
|
}
|
||||||
var fileReader io.ReadCloser
|
var fileReader io.ReadCloser
|
||||||
fileReader, err = fs.storage.ReadFile(minioMetaBucket, multipartPartFile, 0)
|
fileReader, err = fs.storage.ReadFile(minioMetaBucket, multipartPartFile, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1244,11 +1244,14 @@ func (s *MyAPISuite) TestObjectMultipart(c *C) {
|
|||||||
c.Assert(len(newResponse.UploadID) > 0, Equals, true)
|
c.Assert(len(newResponse.UploadID) > 0, Equals, true)
|
||||||
uploadID := newResponse.UploadID
|
uploadID := newResponse.UploadID
|
||||||
|
|
||||||
|
// Create a byte array of 5MB.
|
||||||
|
data := bytes.Repeat([]byte("0123456789abcdef"), 5*1024*1024/16)
|
||||||
|
|
||||||
hasher := md5.New()
|
hasher := md5.New()
|
||||||
hasher.Write([]byte("hello world"))
|
hasher.Write(data)
|
||||||
md5Sum := hasher.Sum(nil)
|
md5Sum := hasher.Sum(nil)
|
||||||
|
|
||||||
buffer1 := bytes.NewReader([]byte("hello world"))
|
buffer1 := bytes.NewReader(data)
|
||||||
request, err = s.newRequest("PUT", testAPIFSCacheServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=1", int64(buffer1.Len()), buffer1)
|
request, err = s.newRequest("PUT", testAPIFSCacheServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=1", int64(buffer1.Len()), buffer1)
|
||||||
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
@ -1258,7 +1261,14 @@ func (s *MyAPISuite) TestObjectMultipart(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(response1.StatusCode, Equals, http.StatusOK)
|
c.Assert(response1.StatusCode, Equals, http.StatusOK)
|
||||||
|
|
||||||
buffer2 := bytes.NewReader([]byte("hello world"))
|
// Byte array one 1 byte.
|
||||||
|
data = []byte("0")
|
||||||
|
|
||||||
|
hasher = md5.New()
|
||||||
|
hasher.Write(data)
|
||||||
|
md5Sum = hasher.Sum(nil)
|
||||||
|
|
||||||
|
buffer2 := bytes.NewReader(data)
|
||||||
request, err = s.newRequest("PUT", testAPIFSCacheServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=2", int64(buffer2.Len()), buffer2)
|
request, err = s.newRequest("PUT", testAPIFSCacheServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=2", int64(buffer2.Len()), buffer2)
|
||||||
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
@ -1279,6 +1279,13 @@ func (s *MyAPIXLSuite) TestObjectMultipart(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(response1.StatusCode, Equals, http.StatusOK)
|
c.Assert(response1.StatusCode, Equals, http.StatusOK)
|
||||||
|
|
||||||
|
// Create a byte array of 1 byte.
|
||||||
|
data = []byte("0")
|
||||||
|
|
||||||
|
hasher = md5.New()
|
||||||
|
hasher.Write(data)
|
||||||
|
md5Sum = hasher.Sum(nil)
|
||||||
|
|
||||||
buffer2 := bytes.NewReader(data)
|
buffer2 := bytes.NewReader(data)
|
||||||
request, err = s.newRequest("PUT", testAPIXLServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=2", int64(buffer2.Len()), buffer2)
|
request, err = s.newRequest("PUT", testAPIXLServer.URL+"/objectmultiparts/object?uploadId="+uploadID+"&partNumber=2", int64(buffer2.Len()), buffer2)
|
||||||
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
request.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(md5Sum))
|
||||||
|
@ -124,7 +124,7 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload
|
|||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
|
|
||||||
// Loop through all parts, validate them and then commit to disk.
|
// Loop through all parts, validate them and then commit to disk.
|
||||||
for _, part := range parts {
|
for i, part := range parts {
|
||||||
// Construct part suffix.
|
// Construct part suffix.
|
||||||
partSuffix := fmt.Sprintf("%.5d.%s", part.PartNumber, part.ETag)
|
partSuffix := fmt.Sprintf("%.5d.%s", part.PartNumber, part.ETag)
|
||||||
multipartPartFile := path.Join(mpartMetaPrefix, bucket, object, uploadID, partSuffix)
|
multipartPartFile := path.Join(mpartMetaPrefix, bucket, object, uploadID, partSuffix)
|
||||||
@ -136,7 +136,8 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload
|
|||||||
}
|
}
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if !isMinAllowedPartSize(fi.Size) {
|
// All parts except the last part has to be atleast 5MB.
|
||||||
|
if (i < len(parts)-1) && !isMinAllowedPartSize(fi.Size) {
|
||||||
return "", PartTooSmall{}
|
return "", PartTooSmall{}
|
||||||
}
|
}
|
||||||
// Update metadata parts.
|
// Update metadata parts.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user