skip to Main Content

I’d like to add file size validation to our signed urls, making sure the client uploads a file of exactly the size I signed it with.
However, when I do this :

"conditions": [
    {"acl": "public-read"},
    .... ,
    ["content-length-range", 1024, 1024]
]

For small files, it works.
But a bit larger files, for example 25mb, it results in EntityTooSmall error.

It starts working only if I set the minimum to 0 like this :

["content-length-range", 0, 1024]

But I want to enforce a specific file size, and not a range.
Does S3 not support exact file size match?

EDIT :
Here’s the full code I compiled in Python :

# Create an S3 client
s3 = boto3.client(
    's3',
    aws_access_key_id="...",
    aws_secret_access_key="...",
    region_name="sfo3",
    endpoint_url="https://sfo3.digitaloceanspaces.com",
)

# Specify the bucket name
bucket_name = 'my_bucket'

# Specify the file name
file_name = 'SampleJPGImage_30mbmb.jpeg'

# Get the file size in bytes
file_size = os.path.getsize(file_name)

# Use the file size and content
print("File size:", file_size, "bytes") # Should be 30789588

# Specify the desired file size in bytes
file_size_min = file_size
file_size_max = file_size

# Sign the policy with your AWS secret key
signedPolicy = s3.generate_presigned_post(
    Bucket=bucket_name,
    Key=file_name,
    Fields={
        "acl": "public-read",
        "key": file_name,
    },
    Conditions=[
        {"acl": "public-read"},
        {"key": file_name},
        ["content-length-range", file_size_min, file_size_max]
    ],
    ExpiresIn=3600
)

# Use the signed policy to upload the file
with open(file_name, 'rb') as f:
    print()
    resp = requests.post(signedPolicy['url'], data=signedPolicy['fields'], files={'file': f})
    print(resp)
    print(resp.content)

2

Answers


  1. Unfortunately, no. You can specify only a range. I would check if the file size limit is specified correctly. This error likely indicates that the calculation wasn’t right.

    To test it further, I’d suggest generating a file with the exact size using e.g. dd tool, like this

    dd if=/dev/zero of=test-file-1 bs=26214400 count=1
    

    Then try to upload it. In this case, your range must be [26214400,26214400].

    Login or Signup to reply.
  2. I managed to test with Postman an exact file size and everything is working correctly.
    The condition that I used is:

    const Conditions = [
        ["content-length-range", 30789588, 30789588],
        ["eq", "$Content-Type", "image/jpeg"]
    ];
    

    I downloaded the 30MB file from here: https://sample-videos.com/download-sample-jpg-image.php

    When I change the size of the content length to 30789587 I get the following:

    <Error>
        <Code>EntityTooLarge</Code>
        <Message>Your proposed upload exceeds the maximum allowed size</Message>
        <ProposedSize>30789588</ProposedSize>
        <MaxSizeAllowed>30789587</MaxSizeAllowed>
    </Error> 
    

    And with a content length of 30789589:

    <Error>
        <Code>EntityTooSmall</Code>
        <Message>Your proposed upload is smaller than the minimum allowed size</Message>
        <ProposedSize>30789588</ProposedSize>
        <MinSizeAllowed>30789589</MinSizeAllowed>
    </Error> 
    

    Test with the same file I used and let’s see if it works for you.

    Edit

    Executing the Python code to DigitalOcean Spaces gave the same error: EntityTooSmall without any other information.

    Executing the same code to AWS S3 is working correctly. Also, the error message, when I change the range, is more useful.

    It seems something with the range is not implemented correctly in DigitalOcean Spaces

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search