本地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配置

浏览器错误信息
Chrome控制台错误

Chrome预检OPTIONS请求及响应头

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)
问题原因分析
- S3 CORS配置生效延迟:AWS S3的CORS配置修改或新存储桶的配置,可能需要数分钟到数小时才能在全球边缘节点同步生效,初期的错误可能是配置未完全落地。
- 浏览器缓存影响:浏览器可能缓存了早期无效的CORS预检响应,数小时后缓存过期,新的请求获取到了正确的CORS配置。
- 本地开发代理临时异常:如果本地开发使用了跨域代理,可能存在代理配置的临时缓存或异常,后续自动恢复后问题解决。
内容的提问来源于stack exchange,提问作者reemwn
相关产品推荐
相关产品推荐

