节目概要: 我正在尝试将图像上传到 Next.js 无服务器后端。我使用 formData() 附加/设置数据并使用 axios 将其 POST 到后端。 在后端,我从 NextRequest 请求 formData(),将其更改为缓冲区并将其保存在服务器文件系统中。
问题: 每当我在前端启动发布时,我都会在 Next.js 控制台上看到错误,提示
TypeError: s is not a function
。
完整错误:
TypeError: s is not a function
at PATH\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:37:5830
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async tX (PATH\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:37:5207)
at async rl (PATH\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:38:22994)
at async doRender (PATH\node_modules\next\dist\server\base-server.js:1407:30)
at async cacheEntry.responseCache.get.routeKind (PATH\node_modules\next\dist\server\base-server.js:1571:28)
at async DevServer.renderToResponseWithComponentsImpl (PATH\node_modules\next\dist\server\base-server.js:1479:28)
at async DevServer.renderErrorToResponseImpl (PATH\node_modules\next\dist\server\base-server.js:2104:24)
at async pipe.req.req (PATH\node_modules\next\dist\server\base-server.js:1982:30)
at async DevServer.pipeImpl (PATH\node_modules\next\dist\server\base-server.js:902:25)
客户端(page.tsx):
"use client";
import React from "react";
import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";
import { useRouter } from "next/navigation";
import axios from "axios";
// Dynamically import ReactQuill to ensure it's only loaded on the client side
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
var toolbarOptions = [
// toolbar options
];
const BLOG_API = "/api/blogs";
export default function WriteBlogPage() {
const router = useRouter();
const [title, setTitle] = React.useState("");
const [image, setImage] = React.useState<File>();
const [content, setContent] = React.useState("");
const [slug, setSlug] = React.useState("");
const handleContentChange = (value: any) => {
setContent(value);
};
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setSlug(title.replaceAll(" ", "-").toLowerCase());
if (!image || !title || !content || !slug) return;
try {
const data = new FormData();
data.append("image", image, image.name);
data.append("title", title);
data.append("content", content);
data.append("slug", slug);
const response = await axios.post(BLOG_API, data);
if (response.status === 200) {
router.push("/");
} else {
console.error("Error posting the blog");
}
} catch (error) {
console.error("Error posting the blog:", error);
}
};
return (
<form onSubmit={handleFormSubmit}>
<div className="w-full">
{
<ReactQuill
value={content}
onChange={handleContentChange}
modules={{
toolbar: toolbarOptions,
}}
className="text-center"
placeholder="Write an epic"
/>
}
</div>
<input
type="file"
accept="image/*"
onChange={(e) => setImage(e.target.files?.[0])}
/>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<button
type="submit">
Publish
</button>
</form>
);
}
服务器(route.ts):
// Import necessary modules and models
import { NextRequest, NextResponse } from "next/server";
import { dbConnect as connect } from "@/dbConfig/dbConfig";
import Blog from "@/models/blogModel";
import NodeCache from "node-cache";
import path, { join } from "path";
import { writeFile } from "fs";
// Connect to the database
connect();
// NodeCache configuration for caching
const cache = new NodeCache({
stdTTL: 1800,
checkperiod: 300,
});
export const config = {
api: {
bodyParser: false,
},
};
// POST route for creating a new blog
export async function POST(req: NextRequest, res: NextResponse) {
try {
const data = await req.formData();
const image: File | null = data.get("image") as unknown as File;
const title: String | null = data.get("title") as unknown as String;
const content: String | null = data.get("content") as unknown as String;
const slug: String | null = data.get("slug") as unknown as String;
if (!image || !title || !content || !slug) {
return NextResponse.json({
success: false,
message: "Please pass all necessary data",
});
}
const blogTitle = await Blog.findOne({ title });
if (blogTitle) {
return NextResponse.json({
success: false,
message:
"Already posted. More than one blog of the same title is not allowed",
});
}
const bytes = await image.arrayBuffer();
const buffer = Buffer.from(bytes);
const path = join("/","public/uploads/blogs/cover", image.name);
await writeFile(path, buffer, (error) => {
return NextResponse.json({
success: false,
message: "File save unsuccessful. Please try again.",
});
});
const coverImagePath = join("/uploads/blogs/cover", image.name)
const blog = new Blog({
coverImagePath,
title,
content,
slug,
});
const savedBlog = await blog.save();
cache.del("blogs");
return NextResponse.json({
message: "Blog posted successfully",
success: true,
savedBlog,
});
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
我尝试过的:
使用NextApiRequest/NextApiResponse:说我无法像
Property 'formData' does not exist on type 'NextApiRequest'
那样访问.formData()。
使用multer并存储图像,但我仍然在控制台上遇到相同的错误。
我几个小时前刚刚遇到同样的问题。
事实证明,我没有将 api 文件夹放在应用程序文件夹中,这是保存它的正确位置,并且我认为错误是因为配置或依赖项问题导致了问题(因为我没有它在正确的地方...)
你可以查看Next.js的官方文档,我在阅读此页时就明白了,只需查看Convention部分即可,它说:“Route Handlers 是在app 目录下的route.js|ts 文件中定义的:路由处理程序可以嵌套在app目录中,类似于page.js和layout.js。但是不能有与page.js处于同一路由段级别的route.js文件。”
[https://nextjs.org/docs/app/building-your-application/routing/route-handlers][https://nextjs.org/docs/app/building-your-application/routing/route-handlers ]
希望这对你有帮助....