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

NextJS+ tRPC+AWS S3图片上传遇跨域403错误求助

解决NextJS + tRPC + AWS S3图片上传跨域问题

问题场景

开发基于NextJS的应用,采用tRPC和AWS S3实现图片上传功能,提交表单时触发跨域错误,提示Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin。

相关代码

表单提交逻辑

async function onSubmit(data: z.infer<typeof schema>) {
    console.log(data)
    const { file } = data

    if (!file) return null

    // Get upload url
    const { url, fields } = await createURL()

    const formData = new FormData()
    Object.entries(fields).forEach(([key, value]) => {
        formData.append(key, value as string)
    })
    formData.append('file', file)
    
    const uploadResponse = await fetch(url, {
        method: 'POST',
        body: formData,
    })

    if (uploadResponse.ok) {
        console.log("Upload successful!")
    } else {
        console.error('S3 Upload Error:', uploadResponse)
    }

    console.log(uploadResponse)
}

tRPC预签名URL路由

import { createPresignedPost } from "@aws-sdk/s3-presigned-post";

export const fileRouter = createTRPCRouter({
    createURL: protectedProcedure.mutation(async ({ ctx }) => {

        const { userId } = ctx
        const contentType = "image/"

        const file = await db.file.create({
            data: {
                userId
            }
        })

        const presignedPost = await createPresignedPost(s3Client, {
            Bucket: process.env.AWS_BUCKET!,
            Key: `${userId}/${file.id}`,
            Conditions: [
                ['content-length-range', 0, 10485760], // up to 10 MB
                ['starts-with', '$Content-Type', contentType],
            ],
            Fields: {
                acl: 'public-read',
                'Content-Type': contentType,
            },
            Expires: 600,
        })

        return presignedPost
    })
})

错误信息

[Error] Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. Status code: 403
[Error] Fetch API cannot load https://next-stack-app.s3.us-east-2.amazonaws.com/ due to access control checks.
[Error] Failed to load resource: Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. Status code: 403 (next-stack-app.s3.us-east-2.amazonaws.com, line 0)
[Error] Unhandled Promise Rejection: TypeError: Load failed
(anonymous function) (index.esm.mjs:2196)

解决方案

1. 配置S3存储桶CORS规则

这是解决跨域问题的核心步骤:

  • 登录AWS控制台,找到目标S3存储桶
  • 切换到「权限」标签页,找到「跨域资源共享(CORS)」配置项
  • 替换现有规则为以下内容(根据环境调整AllowedOrigins):
[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET", "POST", "PUT"],
        "AllowedOrigins": ["http://localhost:3000"],
        "ExposeHeaders": ["ETag"]
    }
]

注意:生产环境需将AllowedOrigins替换为实际业务域名,例如["https://your-app-domain.com"]

2. 验证预签名Post配置

检查tRPC路由中的contentType设置:当前代码中contentType = "image/",虽能匹配所有图片类型,但建议改为"image/*"以更清晰;同时确保FormData中正确传递了文件的原始Content-Type(浏览器会自动为File对象设置,无需手动修改)。

3. 等待配置生效

AWS S3的CORS配置变更可能需要1-5分钟生效,配置完成后重新测试上传功能即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:20:35