mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
api: Increase the maximum object size limit from 5GiB to 16GiB. (#3834)
The globalMaxObjectSize limit is instilled in S3 spec perhaps due to certain limitations on S3 infrastructure. For minio we don't have such limitations and we can stream a larger file instead. So we are going to bump this limit to 16GiB. Fixes #3825
This commit is contained in:
parent
28c53a3555
commit
bc52d911ef
@ -1239,16 +1239,16 @@ func TestWriteSetConfigResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testPeers := []adminPeer{
|
testPeers := []adminPeer{
|
||||||
adminPeer{
|
{
|
||||||
addr: "localhost:9001",
|
addr: "localhost:9001",
|
||||||
},
|
},
|
||||||
adminPeer{
|
{
|
||||||
addr: "localhost:9002",
|
addr: "localhost:9002",
|
||||||
},
|
},
|
||||||
adminPeer{
|
{
|
||||||
addr: "localhost:9003",
|
addr: "localhost:9003",
|
||||||
},
|
},
|
||||||
adminPeer{
|
{
|
||||||
addr: "localhost:9004",
|
addr: "localhost:9004",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileSize > lengthRange.Max || fileSize > maxObjectSize {
|
if fileSize > lengthRange.Max || isMaxObjectSize(fileSize) {
|
||||||
errorIf(err, "Unable to create object.")
|
errorIf(err, "Unable to create object.")
|
||||||
writeErrorResponse(w, toAPIErrorCode(errDataTooLarge), r.URL)
|
writeErrorResponse(w, toAPIErrorCode(errDataTooLarge), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -46,9 +46,9 @@ func registerHandlers(mux *router.Router, handlerFns ...HandlerFunc) http.Handle
|
|||||||
// which is more than enough to accommodate any form data fields and headers.
|
// which is more than enough to accommodate any form data fields and headers.
|
||||||
const requestFormDataSize = 64 * humanize.MiByte
|
const requestFormDataSize = 64 * humanize.MiByte
|
||||||
|
|
||||||
// For any HTTP request, request body should be not more than 5GiB + requestFormDataSize
|
// For any HTTP request, request body should be not more than 16GiB + requestFormDataSize
|
||||||
// where, 5GiB is the maximum allowed object size for object upload.
|
// where, 16GiB is the maximum allowed object size for object upload.
|
||||||
const requestMaxBodySize = 5*humanize.GiByte + requestFormDataSize
|
const requestMaxBodySize = globalMaxObjectSize + requestFormDataSize
|
||||||
|
|
||||||
type requestSizeLimitHandler struct {
|
type requestSizeLimitHandler struct {
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
|
@ -628,7 +628,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// maximum copy size for multipart objects in a single operation
|
/// maximum copy size for multipart objects in a single operation
|
||||||
if isMaxObjectSize(length) {
|
if isMaxAllowedPartSize(length) {
|
||||||
writeErrorResponse(w, ErrEntityTooLarge, r.URL)
|
writeErrorResponse(w, ErrEntityTooLarge, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -637,6 +637,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
// object is same then only metadata is updated.
|
// object is same then only metadata is updated.
|
||||||
partInfo, err := objectAPI.CopyObjectPart(srcBucket, srcObject, dstBucket, dstObject, uploadID, partID, startOffset, length)
|
partInfo, err := objectAPI.CopyObjectPart(srcBucket, srcObject, dstBucket, dstObject, uploadID, partID, startOffset, length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errorIf(err, "Unable to perform CopyObjectPart %s/%s", srcBucket, srcObject)
|
||||||
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
|
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -687,7 +688,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// maximum Upload size for multipart objects in a single operation
|
/// maximum Upload size for multipart objects in a single operation
|
||||||
if isMaxObjectSize(size) {
|
if isMaxAllowedPartSize(size) {
|
||||||
writeErrorResponse(w, ErrEntityTooLarge, r.URL)
|
writeErrorResponse(w, ErrEntityTooLarge, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -840,7 +840,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
req.ContentLength = -1
|
req.ContentLength = -1
|
||||||
req.TransferEncoding = []string{}
|
req.TransferEncoding = []string{}
|
||||||
case TooBigObject:
|
case TooBigObject:
|
||||||
req.ContentLength = maxObjectSize + 1
|
req.ContentLength = globalMaxObjectSize + 1
|
||||||
}
|
}
|
||||||
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
||||||
@ -883,7 +883,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
reqV2.ContentLength = -1
|
reqV2.ContentLength = -1
|
||||||
reqV2.TransferEncoding = []string{}
|
reqV2.TransferEncoding = []string{}
|
||||||
case TooBigObject:
|
case TooBigObject:
|
||||||
reqV2.ContentLength = maxObjectSize + 1
|
reqV2.ContentLength = globalMaxObjectSize + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
@ -2722,7 +2722,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin
|
|||||||
{
|
{
|
||||||
objectName: testObject,
|
objectName: testObject,
|
||||||
reader: bytes.NewReader([]byte("hello")),
|
reader: bytes.NewReader([]byte("hello")),
|
||||||
partNumber: strconv.Itoa(maxPartID + 1),
|
partNumber: strconv.Itoa(globalMaxPartID + 1),
|
||||||
fault: None,
|
fault: None,
|
||||||
accessKey: credentials.AccessKey,
|
accessKey: credentials.AccessKey,
|
||||||
secretKey: credentials.SecretKey,
|
secretKey: credentials.SecretKey,
|
||||||
@ -2880,7 +2880,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin
|
|||||||
// Setting the content length to a value greater than the max allowed size of a part.
|
// Setting the content length to a value greater than the max allowed size of a part.
|
||||||
// Used in test case 4.
|
// Used in test case 4.
|
||||||
case TooBigObject:
|
case TooBigObject:
|
||||||
req.ContentLength = maxObjectSize + 1
|
req.ContentLength = globalMaxObjectSize + 1
|
||||||
// Malformed signature.
|
// Malformed signature.
|
||||||
// Used in test case 6.
|
// Used in test case 6.
|
||||||
case BadSignature:
|
case BadSignature:
|
||||||
|
32
cmd/utils.go
32
cmd/utils.go
@ -170,27 +170,41 @@ func checkValidMD5(md5 string) ([]byte, error) {
|
|||||||
|
|
||||||
/// http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadingObjects.html
|
/// http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadingObjects.html
|
||||||
const (
|
const (
|
||||||
// maximum object size per PUT request is 5GiB
|
// Maximum object size per PUT request is 16GiB.
|
||||||
maxObjectSize = 5 * humanize.GiByte
|
// This is a divergence from S3 limit on purpose to support
|
||||||
// minimum Part size for multipart upload is 5MiB
|
// use cases where users are going to upload large files
|
||||||
minPartSize = 5 * humanize.MiByte
|
// using 'curl' and presigned URL.
|
||||||
// maximum Part ID for multipart upload is 10000 (Acceptable values range from 1 to 10000 inclusive)
|
globalMaxObjectSize = 16 * humanize.GiByte
|
||||||
maxPartID = 10000
|
|
||||||
|
// Minimum Part size for multipart upload is 5MiB
|
||||||
|
globalMinPartSize = 5 * humanize.MiByte
|
||||||
|
|
||||||
|
// Maximum Part size for multipart upload is 5GiB
|
||||||
|
globalMaxPartSize = 5 * humanize.GiByte
|
||||||
|
|
||||||
|
// Maximum Part ID for multipart upload is 10000
|
||||||
|
// (Acceptable values range from 1 to 10000 inclusive)
|
||||||
|
globalMaxPartID = 10000
|
||||||
)
|
)
|
||||||
|
|
||||||
// isMaxObjectSize - verify if max object size
|
// isMaxObjectSize - verify if max object size
|
||||||
func isMaxObjectSize(size int64) bool {
|
func isMaxObjectSize(size int64) bool {
|
||||||
return size > maxObjectSize
|
return size > globalMaxObjectSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Check if part size is more than maximum allowed size.
|
||||||
|
func isMaxAllowedPartSize(size int64) bool {
|
||||||
|
return size > globalMaxPartSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if part size is more than or equal to minimum allowed size.
|
// Check if part size is more than or equal to minimum allowed size.
|
||||||
func isMinAllowedPartSize(size int64) bool {
|
func isMinAllowedPartSize(size int64) bool {
|
||||||
return size >= minPartSize
|
return size >= globalMinPartSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// isMaxPartNumber - Check if part ID is greater than the maximum allowed ID.
|
// isMaxPartNumber - Check if part ID is greater than the maximum allowed ID.
|
||||||
func isMaxPartID(partID int) bool {
|
func isMaxPartID(partID int) bool {
|
||||||
return partID > maxPartID
|
return partID > globalMaxPartID
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(stringList []string, element string) bool {
|
func contains(stringList []string, element string) bool {
|
||||||
|
@ -110,12 +110,12 @@ func TestMaxObjectSize(t *testing.T) {
|
|||||||
// Test - 1 - maximum object size.
|
// Test - 1 - maximum object size.
|
||||||
{
|
{
|
||||||
true,
|
true,
|
||||||
maxObjectSize + 1,
|
globalMaxObjectSize + 1,
|
||||||
},
|
},
|
||||||
// Test - 2 - not maximum object size.
|
// Test - 2 - not maximum object size.
|
||||||
{
|
{
|
||||||
false,
|
false,
|
||||||
maxObjectSize - 1,
|
globalMaxObjectSize - 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, s := range sizes {
|
for i, s := range sizes {
|
||||||
@ -135,12 +135,12 @@ func TestMinAllowedPartSize(t *testing.T) {
|
|||||||
// Test - 1 - within minimum part size.
|
// Test - 1 - within minimum part size.
|
||||||
{
|
{
|
||||||
true,
|
true,
|
||||||
minPartSize + 1,
|
globalMinPartSize + 1,
|
||||||
},
|
},
|
||||||
// Test - 2 - smaller than minimum part size.
|
// Test - 2 - smaller than minimum part size.
|
||||||
{
|
{
|
||||||
false,
|
false,
|
||||||
minPartSize - 1,
|
globalMinPartSize - 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,12 +161,12 @@ func TestMaxPartID(t *testing.T) {
|
|||||||
// Test - 1 part number within max part number.
|
// Test - 1 part number within max part number.
|
||||||
{
|
{
|
||||||
false,
|
false,
|
||||||
maxPartID - 1,
|
globalMaxPartID - 1,
|
||||||
},
|
},
|
||||||
// Test - 2 part number bigger than max part number.
|
// Test - 2 part number bigger than max part number.
|
||||||
{
|
{
|
||||||
true,
|
true,
|
||||||
maxPartID + 1,
|
globalMaxPartID + 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user