如何在 next.js API 路由中上传图像和文本?我已经准备好了前端。这是用于上传图像和文本的 onSubmit 函数。请指出我在这里做错了什么。 有人可以帮我解释一下吗,这样我就可以理解它以供将来参考。
谢谢
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const res = await fetch("/api/articles", {
method: "POST",
body: JSON.stringify({ formData }),
headers: { "content-type": "application/json" },
});
if (!res.ok) {
throw new Error("failed to create ticket.");
}
router.refresh();
router.push("/");
}
这是 Api 端点
import Post from "@/app/(model)/post";
import { writeFile } from "fs/promises";
import { NextRequest, NextResponse } from "next/server";
import { join } from "path";
export async function POST(req:NextRequest, data: FormData) {
'use server'
console.log('post created')
try {
const body = await req.json()
const file: File | null = data.get("file") as unknown as File;
if (!file) {
throw new Error("No file uploaded");
}
const postData = body.formData
const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
const path = join('/', 'tmp', file.name)
await Post.create(postData)
await writeFile(path, buffer)
return NextResponse.json({message: 'Post Created'}, {status: 201})
} catch (error) {
return NextResponse.json({message: 'Error', error}, {status: 500})
}
}
您当前的前端代码尝试以 JSON 形式发送表单数据,这不适合文件上传。相反,您应该使用
FormData
来处理文件和文本。以下是修改您的 handleSubmit
: 的方法
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
// Initialize FormData
const formData = new FormData(e.currentTarget); // Assuming 'e.currentTarget' is your form
// Append additional data if necessary
// formData.append('key', 'value');
const res = await fetch("/api/articles", {
method: "POST",
body: formData, // Send formData directly without JSON.stringify
// Remove 'content-type': 'application/json' header since it's not JSON anymore
});
if (!res.ok) {
throw new Error("failed to create ticket.");
}
router.refresh();
router.push("/");
}
POST
函数参数不正确。 Next.js API 路由应采用 req
(请求对象)和 res
(响应对象)作为参数。在 Next.js 中读取服务器端的表单数据应该使用 next-connect
或类似的中间件,因为 Next.js 不会在服务器端本地解析 FormData
。
安装
next-connect
和formidable
:
npm install next-connect formidable
修改你的API路由以正确处理
FormData
:
import nextConnect from 'next-connect';
import { promises as fs } from 'fs';
import path from 'path';
import formidable from 'formidable';
import Post from '@/app/(model)/post';
const apiRoute = nextConnect({
onError(error, req, res) {
res.status(501).json({ error: `Sorry something Happened! ${error.message}` });
},
onNoMatch(req, res) {
res.status(405).json({ error: `Method '${req.method}' Not Allowed` });
},
});
apiRoute.post(async (req, res) => {
const form = new formidable.IncomingForm();
form.uploadDir = "./public/uploads";
form.keepExtensions = true;
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: 'Something went wrong during the file upload' });
return;
}
// Process the file, save to your desired location
const file = files.file; // This depends on the 'name' attribute in your form
const postData = fields; // Your text fields
// Move or use the file as needed
const newPath = path.join(form.uploadDir, file.originalFilename);
await fs.rename(file.filepath, newPath);
// Save your postData into the database
await Post.create(postData);
res.status(201).json({ message: 'Post created successfully' });
});
});
export const config = {
api: {
bodyParser: false, // Disabling bodyParser is important here
},
};
export default apiRoute;