You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地React环境通过S3预签名URL上传遇CORS错误,非浏览器环境正常

本地React应用通过S3预签名URL上传MP4文件遇CORS错误,数小时后自动恢复

问题现象

本地开发环境的React应用,使用S3预签名URL上传video/mp4文件时触发CORS错误,但用Python脚本发起PUT请求能成功上传,说明预签名URL本身有效。未修改任何配置的情况下,存储桶创建数小时后问题自动消失,预签名URL不再返回CORS错误。

预签名URL生成代码(Lambda函数)

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
        })
    }

React客户端上传代码

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

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

        try {
            // 通过Lambda URL获取预签名上传地址
            const uploadUrl: string = await axios
                .get(
                    "https://somethingsomething.lambda-url.eu-west-1.on.aws/",
                )
                .then((response) => response.data.upload_url);


            // 上传文件到预签名URL
            const response = await axios.put(uploadUrl, file, {
                headers: {
                    "content-type": file.type,
                },
            });
            
            if (response.status === 200) {
                setUploadSuccess(true);
            } else {
                setError("上传失败,请重试。");
                setUploadSuccess(false);
            }
        } catch (error) {
            setError("上传失败,请重试。");
            console.error(error);
            setUploadSuccess(false);
        } finally {
            setUploading(false);
        }
    };

S3存储桶CORS配置

CORS配置截图

浏览器错误信息

Chrome控制台错误

Chrome错误截图

Chrome预检OPTIONS请求及响应头

预检请求响应截图

Firefox控制台错误

Firefox错误截图

Firefox网络面板

Firefox网络面板截图

可正常上传的Python脚本

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("文件上传成功。")
            else:
                print(f"文件上传失败。状态码: {response.status_code}")
                print(response.text)
        except Exception as e:
            print(f"发生错误: {e}")

if __name__ == "__main__":
    file_path = 'file_example_MP4_480_1_5MG.mp4'  
    presigned_url = "手动复制的预签名URL"
    upload_file_to_s3(file_path, presigned_url)

问题原因分析

  1. S3 CORS配置生效延迟:AWS S3的CORS配置修改或新存储桶的配置,可能需要数分钟到数小时才能在全球边缘节点同步生效,初期的错误可能是配置未完全落地。
  2. 浏览器缓存影响:浏览器可能缓存了早期无效的CORS预检响应,数小时后缓存过期,新的请求获取到了正确的CORS配置。
  3. 本地开发代理临时异常:如果本地开发使用了跨域代理,可能存在代理配置的临时缓存或异常,后续自动恢复后问题解决。

内容的提问来源于stack exchange,提问作者reemwn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:37:06