2

I'm trying to generate s3 presigned url to upload video/mp4 files to a bucket from react app client in development mode in my localhost. However, I'm getting CORS error. But when I do the put request from a python script it goes through, which establishes that my presigned url is working. What I found odd though, the whole thing starts working after a few hours without any changes to the setup, so basically after the bucket is a few hours old. I mean the presigned url stops giving cors error.

This is how I'm generating presigned url:

import os
import boto3
from botocore.exceptions import NoCredentialsError
import uuid
import json

def handler(event, context):
    bucket_name = os.environ['BUCKET_NAME']
    object_name = str(uuid.uuid4())+ ".mp4"
    aws_region = "eu-west-1"
    s3_client = boto3.client('s3', region_name=aws_region)


    try:
        response = s3_client.generate_presigned_url('put_object',
                                                    Params={'Bucket': bucket_name,
                                                            'Key': object_name,
                                                            'ContentType': 'video/mp4'
                                                            },
                                                    ExpiresIn=3600,
                                                    HttpMethod='PUT',
                                                    )
    except NoCredentialsError:
        return {
            'statusCode': 400,
            'body': 'No AWS credentials found'
        }

    return {
        'statusCode': 200,
        'body': json.dumps({
            'upload_url': response,
            'object_name': object_name
        })
    }

This is my how my client react app is making the request:

onst uploadFile = async (file: File) => {
        setUploading(true);
        setUploadSuccess(null);

        const formData = new FormData();
        formData.append("file", file);

        try {
            // gets the presigned URL for uploading the file via lambda function url
            const uploadUrl: string = await axios
                .get(
                    "https://somethingsomething.lambda-url.eu-west-1.on.aws/",
                )
                .then((response) => response.data.upload_url);


            // uploads the file to the presigned URL
            const response = await axios.put(uploadUrl, file, {
                headers: {
                    "content-type": file.type,
                },
            });
            
            if (response.status === 200) {
                setUploadSuccess(true);
            } else {
                setError("Upload failed. Please try again.");
                setUploadSuccess(false);
            }
        } catch (error) {
            setError("Upload failed. Please try again.");
            console.error(error);
            setUploadSuccess(false);
        } finally {
            setUploading(false);
        }
    };

This is the CORS configuration on the S3 bucket: enter image description here

Error in Chrome console: enter image description here Preflight option request and response header: enter image description here Error in Firefox console: enter image description here Network tab in Firefox: enter image description here Python code that uploads without any issue:

import requests

def upload_file_to_s3(file_path, presigned_url):
    with open(file_path, 'rb') as file:
        try:
            response = requests.put(presigned_url, data=file)
            if response.status_code == 200:
                print("File uploaded successfully.")
            else:
                print(f"Failed to upload file. Status code: {response.status_code}")
                print(response.text)
        except Exception as e:
            print(f"An error occurred: {e}")

if __name__ == "__main__":
    file_path = 'file_example_MP4_480_1_5MG.mp4'  
    presigned_url = "MANUALLY_COPY_PASTED_URL"
    upload_file_to_s3(file_path, presigned_url)
0

1 Answer 1

0

I found the solution here:

S3 presigned URL works 90 minutes after bucket creation

import os
import boto3
from botocore.exceptions import NoCredentialsError
import uuid
import json
from botocore.client import Config


def handler(event, context):
    region = "eu-west-1"
    bucket_name = os.environ['BUCKET_NAME']
    object_name = str(uuid.uuid4())+ ".mp4"
    s3_client = boto3.client('s3', config=Config(signature_version='s3v4'), region_name=region,
                             endpoint_url=('https://s3.'+ region + '.amazonaws.com'))


    try:
        response = s3_client.generate_presigned_url(ClientMethod='put_object',
                                                    Params={'Bucket': bucket_name,
                                                            'Key': object_name,
                                                            'ContentType': 'video/mp4' },
                                                    ExpiresIn=3600,
                                                    HttpMethod='PUT',
                                                    )
    except NoCredentialsError:
        return {
            'statusCode': 400,
            'body': 'No AWS credentials found'
        }

    return {
        'statusCode': 200,
        'body': json.dumps({
            'upload_url': response,
            'object_name': object_name
        })
    }

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.