如何在 NextJS 中上传图像和一些文本

问题描述 投票:0回答:1

如何在 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})
  }
  }
  
  
javascript node.js next.js file-upload
1个回答
0
投票

您当前的前端代码尝试以 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;
© www.soinside.com 2019 - 2024. All rights reserved.