如何在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
相关产品推荐
相关产品推荐

