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

如何在NextJS后端API路由中通过AWS Amplify Gen 2上传图片?

在Next.js后端API路由中实现AWS Amplify Gen2文件上传(带事务+认证解决)

问题背景

在NextJS项目中使用AWS Amplify Gen 2时,需在后端API路由中完成图片上传与数据库更新的原子事务(若上传失败则数据库操作回滚)。尝试使用前端的aws-amplify/storage包中uploadData函数时,因后端缺少前端Authenticator上下文,抛出Unauthorized, Access Denied错误,且官方文档无后端上传示例。

报错代码

import { uploadData } from "aws-amplify/storage";
import { db } from "@/lib/db"; // 假设你的Prisma连接导出在这里

export async function POST(req: Request) {
  try {
    const formData = await req.formData();
    const image = formData.get("image") as File | null;
    const prisma = await db();

    if (image) {
      const filename = image.name;
      const result = await prisma.$transaction(async (tx) => {
        const dbResult = await tx.image.create({
          data: {
            name: image.name,
          },
        });
        await uploadData({
          data: image,
          path: `images/${filename}`,
        });
        return dbResult;
      });
      return Response.json(
        { message: "Image uploaded", result },
        { status: 200 }
      );
    }
    return Response.json({ message: "No image provided" }, { status: 400 });
  } catch (error) {
    console.error(error);
    return Response.json({ error: "Internal server error" }, { status: 500 });
  }
}

解决方案

后端无法直接使用前端的uploadData函数(依赖前端认证上下文),需改用AWS SDK v3直接操作S3,并通过服务器端凭证完成认证。

1. 安装AWS SDK依赖

npm install @aws-sdk/client-s3 @aws-sdk/lib-storage

2. 配置后端S3客户端

利用Amplify Gen2自动注入的环境变量(本地开发通过amplify pull获取,部署时Amplify会自动配置IAM角色权限),初始化S3客户端:

import { S3Client } from "@aws-sdk/client-s3";

const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  // 本地开发时Amplify自动注入凭证,部署时无需手动配置(使用IAM角色)
  credentials: process.env.NODE_ENV === "development" ? {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  } : undefined,
});

3. 修改API路由代码(整合事务与S3上传)

使用@aws-sdk/lib-storage中的Upload类处理文件流式上传,并将数据库操作与上传包裹在Prisma事务中:

import { Upload } from "@aws-sdk/lib-storage";
import { S3Client } from "@aws-sdk/client-s3";
import { db } from "@/lib/db";

const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: process.env.NODE_ENV === "development" ? {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  } : undefined,
});

export async function POST(req: Request) {
  try {
    const formData = await req.formData();
    const image = formData.get("image") as File | null;
    const prisma = await db();

    if (!image) {
      return Response.json({ message: "No image provided" }, { status: 400 });
    }

    const filename = image.name;
    const bucketName = process.env.AMPLIFY_STORAGE_BUCKET_NAME; // Amplify存储桶名称,从环境变量获取

    const result = await prisma.$transaction(async (tx) => {
      // 1. 写入数据库
      const dbResult = await tx.image.create({
        data: {
          name: filename,
        },
      });

      // 2. 将File转换为Buffer
      const fileBuffer = await image.arrayBuffer();

      // 3. 上传到S3
      const upload = new Upload({
        client: s3Client,
        params: {
          Bucket: bucketName,
          Key: `images/${filename}`,
          Body: Buffer.from(fileBuffer),
          ContentType: image.type,
        },
      });

      await upload.done();

      return dbResult;
    });

    return Response.json(
      { message: "Image uploaded", result },
      { status: 200 }
    );
  } catch (error) {
    console.error("Upload failed:", error);
    return Response.json({ error: "Internal server error" }, { status: 500 });
  }
}

4. 权限配置

  • 本地开发:执行amplify pull拉取最新后端配置,Amplify会自动注入正确的凭证环境变量。
  • 部署到Amplify:在Amplify控制台「权限」页面,为后端API的IAM角色添加S3存储桶的PutObject权限(可通过CLI或控制台策略编辑器配置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:13:16