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

如何在Next.js 13 App Router中上传图片至Amazon S3并适配API路由变更

在Next.js 13 App Router中实现S3图片上传

在Next.js 13的App Router中,API路由(app/api/[route]/route.ts)原生支持FormData,无需依赖multer或formidable。你可以直接通过request.formData()获取文件,转换为Buffer后调用S3上传函数。以下是修改后的完整代码:

import { NextRequest, NextResponse } from "next/server";
import { v4 as uuid } from "uuid";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3Client = new S3Client({
  region: process.env.REGION as string,
  credentials: {
    accessKeyId: process.env.ACCESS_KEY as string,
    secretAccessKey: process.env.SECRET_KEY as string,
  },
});

async function uploadImageToS3(
  file: Buffer,
  fileName: string,
  contentType: string
): Promise<string> {
  // 生成唯一S3对象键,避免文件名冲突
  const s3Key = `${Date.now()}-${uuid()}-${fileName}`;
  
  const params = {
    Bucket: process.env.BUCKET_NAME as string,
    Key: s3Key,
    Body: file,
    ContentType: contentType, // 动态适配文件类型
  };

  const command = new PutObjectCommand(params);
  await s3Client.send(command);

  return s3Key;
}

export async function POST(request: NextRequest) {
  try {
    const formData = await request.formData();
    // 从FormData获取文件,对应前端表单的文件字段名需保持一致(这里假设是"image")
    const file = formData.get("image") as File | null;

    if (!file) {
      return NextResponse.json({ message: "未选择文件" }, { status: 400 });
    }

    // 将File对象转换为Buffer
    const buffer = Buffer.from(await file.arrayBuffer());
    const fileName = file.name;
    const contentType = file.type;

    // 执行S3上传
    const s3Key = await uploadImageToS3(buffer, fileName, contentType);

    return NextResponse.json({ 
      message: "文件上传成功", 
      s3Key: s3Key,
      // 若需返回可访问URL,需确保S3桶配置了公开访问或生成预签名URL
      // fileUrl: `https://${process.env.BUCKET_NAME}.s3.${process.env.REGION}.amazonaws.com/${s3Key}`
    }, { status: 200 });
  } catch (error) {
    console.error("文件上传失败:", error);
    return NextResponse.json({ message: "文件上传失败" }, { status: 500 });
  }
}

关键修改说明

  • 移除冗余依赖:删除multer和formidable,App Router的NextRequest原生支持formData()方法。
  • 动态文件类型:从File对象直接获取type属性,适配png、webp等多种图片格式,不再硬编码image/jpeg。
  • 唯一键生成:结合时间戳和UUID生成S3对象键,避免同名文件覆盖。
  • 完善错误处理:增加文件不存在的判断,返回对应HTTP状态码和提示信息。
  • 返回上传结果:返回S3对象键,方便后续业务逻辑使用(如需访问URL,需确保S3桶权限配置正确)。

前端提交示例(参考)

使用Fetch API提交文件:

async function uploadImage(file) {
  const formData = new FormData();
  formData.append("image", file);

  const response = await fetch("/api/upload", {
    method: "POST",
    body: formData,
  });

  const result = await response.json();
  console.log(result);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:25:37