乐闻世界logo
搜索文章和话题

NextJS 如何在同时上传图片和文本?

6 个月前提问
3 个月前修改
浏览次数87

2个答案

1
2

在 Next.js 中,您通常会处理图片和文本上传到服务器的情况。通常,您会使用一个表单来收集用户输入的文本和图片,然后发送一个 HTTP 请求(通常是 POST 请求)到您的 API 路径。

以下是一个示例流程,说明如何同时上传图片和文本:

  1. 创建一个带有文件输入和文本输入的表单:用户可以在表单中填写文本信息并选择图片文件。

  2. 使用 FormData API 为上传创建数据:在客户端,您可以使用 FormData API 来构建表单数据对象。这允许您将文本和文件数据组合在一起。

  3. 发送带有图片和文本的请求:使用 fetch 或任何其他 HTTP 客户端从客户端发送带有表单数据的 POST 请求到服务器。

  4. 服务器端接收处理:在服务器端,您需要有一个 API 路径来接收这个请求。在 Next.js 中,您可以在 pages/api 目录中创建一个 API 路由处理这个请求。

  5. 存储文件和文本:在服务器端,您可以使用像 multer 这样的中间件来处理图片文件的上传,并将文本数据存储在数据库中。

下面是一个基本的代码示例,说明了如何在 Next.js 应用程序中进行操作。

前端代码 (React 组件)

jsx
import React, { useState } from 'react'; function UploadForm() { const [file, setFile] = useState(null); const [text, setText] = useState(''); const handleFileChange = (e) => { setFile(e.target.files[0]); }; const handleTextChange = (e) => { setText(e.target.value); }; const handleSubmit = async (e) => { e.preventDefault(); // 创建 FormData 对象 const formData = new FormData(); formData.append('image', file); formData.append('text', text); // 发送请求到 /api/upload API 路径 const response = await fetch('/api/upload', { method: 'POST', body: formData, }); // ...处理响应... }; return ( <form onSubmit={handleSubmit}> <input type="text" value={text} onChange={handleTextChange} /> <input type="file" onChange={handleFileChange} /> <button type="submit">Upload</button> </form> ); } export default UploadForm;

后端代码 (Next.js API 路径 /pages/api/upload.js)

javascript
import nextConnect from 'next-connect'; import multer from 'multer'; const upload = multer({ dest: 'uploads/' }); // 配置 multer,定义文件存储位置 const apiRoute = nextConnect({ // 处理任何其他 HTTP 方法 onNoMatch(req, res) { res.status(405).json({ error: `Method ${req.method} Not Allowed` }); }, }); // 处理单个文件上传,文件字段名为 'image' apiRoute.use(upload.single('image')); apiRoute.post((req, res) => { const { text } = req.body; // 这是上传的文本数据 const { file } = req; // 这是上传的文件信息 // 处理文本和文件存储... res.status(200).json({ message: 'File uploaded successfully' }); }); export default apiRoute;

这个简单的例子展示了如何在 Next.js 应用中处理同时上传图片和文本的情况。前端使用 FormData 收集用户输入,而后端使用 next-connectmulter 中间件来处理 multipart/form-data 类型的请求。您可能还需要进一步处理存储逻辑,例如将文件保存到云存储服务,或者将文本数据存储到数据库中。

2024年6月29日 12:07 回复

Your current frontend code attempts to send form data as JSON, which is not suitable for file uploads. Instead, you should use FormData to handle both files and text. Here is how you can modify your handleSubmit:

shell
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 function parameters are incorrect. Next.js API routes should take req (the request object) and res (the response object) as parameters. Reading form data on the server side in Next.js should use next-connect or a similar middleware because Next.js does not natively parse FormData on the server side.

Install next-connect and formidable:

shell
npm install next-connect formidable

Modify your API route to correctly handle FormData:

shell
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;
2024年6月29日 12:07 回复

你的答案