Nextjs 13 强大的解析功能没有反应,备货了

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

Formidable 已库存,根本没有任何响应,API 始终处于待定状态,数周内都没有找到锁定解决方案。

我创建了一个简单的个人资料页面,其中包含表单内的图像,以将其上传到下一个 js 中的 api 处理程序,以便拥有一个完整的堆栈 Web 应用程序,但它始终处于挂起状态:

这是前端代码:

 import React, {FormEvent, useRef, useState} from "react";
 import {useSession} from "next-auth/react";
 import Paper from "@mui/material/Paper";
 
 import {Avatar, Box, Button, Grid, TextField, Typography,} from "@mui/material";
 import FormData from "form-data";
 
 
 const Profile = () => {
 
   const {data: session} = useSession();
 
   const filePathRef = useRef<HTMLInputElement | null>(null);
 
   const initialState = {
     firstName: session?.user.firstname == null ? "" : session?.user.firstname,
     lastName: session?.user.lastname == null ? "" : session?.user.lastname,
     currentPassword: "",
     profilePicUrl: session?.user.profileImage == null ? "" : session?.user.profileImage
   }
 
   // @ts-ignore
   const handleImageChange = (e) => {
     const file = e.target.files[0];
     if (file) {
       const reader = new FileReader();
 
       reader.onloadend = () => {
         const uri = URL.createObjectURL(file)
         setFormData((prevState) => ({
           ...prevState,
           profilePicUrl: uri
         }));
         setFile(file)
       };
       reader.readAsDataURL(file);
     } else {
       setFormData((prevState) => ({
         ...prevState,
         profilePicUrl: ""
       }));
     }
   };
 
   const [formData,
     setFormData] =
       useState(initialState);
 
   const [file,
     setFile] =
       useState<File | null>(null);
 
   const requestState = {
     isError: false,
     message: ""
   }
 
   const [state,
     setState
   ] = useState(requestState)
 
   // @ts-ignore
   const handleFormChange = (event) => {
     const {name, value} = event.target;
     setFormData((prevState) => ({
           ...prevState,
           [name]: value,
         }));
   };
 
   function isFormChanged() {
     return formData.firstName != initialState.firstName ||
         formData.lastName != initialState.lastName ||
         formData.profilePicUrl != initialState.profilePicUrl
   }
 
   const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
     console.log("dasdas")
 
     e.preventDefault();
     if (isFormChanged()) {
 
       const data = new FormData()
       console.log("formData " + formData)
 
       if (file) {
         data.append("firstName", formData.firstName)
         data.append("lastName", formData.lastName)
         data.append("password", formData.currentPassword)
       }
 
       if (file != null) { // @ts-ignore
         data.append("file", file)
       }
 
 
       const response = await fetch(
           '/api/admin', {
             method: 'POST',
             body: data
           });
 
       if (response.ok) {
         setState((prevState) => ({
           ...prevState,
           isError: false,
           message: 'Update successful!'
         }));
       } else {
         setState((prevState) => ({
           ...prevState,
           isError: true,
           message: 'Update failed wrong current password'
         }));
       }
     }
   };
 
   return (
       <>
         <h1>Profile</h1>
         <Box>
           <Typography variant={"h4"} sx={{paddingBottom: 4}}>
             Hey {session ? session?.user?.firstname + " " + session?.user?.lastname : "User"}, welcome to your profile
             👋
           </Typography>
 
           <Paper sx={{padding: "1rem 2rem"}}>
             <Grid container justifyContent="center">
               <Grid item xs={12} sm={8} md={6}>
                 <Box display="flex" flexDirection="column" alignItems="center">
                   <Avatar
                       sx={{
                         height: 100,
                         width: 100,
                         marginBottom: 2,
                       }}
                       onClick={() => {
                         filePathRef.current?.click()
                       }}
                       src={formData.profilePicUrl}
                   />
                   <Typography variant={"h6"} sx={{
                     paddingBottom: 4,
                     color: state.isError ? 'red' : 'green'
                   }}>
                     {state.message}
                   </Typography>
                 </Box>
                 <form
                     method="post"
                     onSubmit={handleSubmit}
                     style={{maxWidth: 600, margin: "0 auto"}}>
                   <Grid container spacing={3}>
                     <Grid item xs={12} sm={6}>
                       <TextField
                           required
                           fullWidth
                           label="First Name"
                           name="firstName"
                           value={formData.firstName}
                           onChange={handleFormChange}
                       />
                     </Grid>
 
                     <Grid item xs={12} sm={6} hidden>
                       <input
                           name="image"
                           type="file"
                           id="image"
                           ref={filePathRef}
                           onChange={handleImageChange}
                       />
                     </Grid>
 
                     <Grid item xs={12} sm={6}>
                       <TextField
                           required
                           fullWidth
                           label="Last Name"
                           name="lastName"
                           value={formData.lastName}
                           onChange={handleFormChange}
                       />
                     </Grid>
                     <Grid item xs={12}>
                       <TextField
                           required
                           fullWidth
                           type="password"
                           label="Current Password"
                           name="currentPassword"
                           value={formData.currentPassword}
                           onChange={handleFormChange}
                       />
                     </Grid>
 
                     <Grid item xs={12}>
                       <Button type="submit" variant="contained" color="primary">
                         Save Changes
                       </Button>
                     </Grid>
                   </Grid>
                 </form>
               </Grid>
             </Grid>
           </Paper>
         </Box>
       </>
   );
 };
 
 
 export default Profile;

后端处理程序:

    import type { NextApiRequest, NextApiResponse } from "next";
    import { IncomingForm } from "formidable";
    
    export default async function handle(request:NextApiRequest,response:NextApiResponse) {
        try {
            console.log(JSON.stringify(request.body))
            await new IncomingForm().parse(request)
            response.status(200).json({b: ""})
        } catch (e) {
            console.log("error " + e)
            response.status(500).json({b: ""})
        }
    }
    
    export const config = {
        Api: {
            bodyParser: false,
        },
    };

我只是想回复但运气不佳。

next.js upload next.js13 multipart formidable
1个回答
0
投票

您不需要

Formidable
来处理 NextJS 13 中的文件,因为它可以开箱即用地处理文件

当您创建新项目时,建议使用

app/
目录。

这里我创建了一个类似的表单,在“/api/home”上提交

const Home = () => {
  return (
    <form
      method="post"
      action="/api/home"
      style={{ color: "gray" }}
      encType="multipart/form-data"
    >
      <div>
        First Name <input type="text" name="firstName" defaultValue="John" />
      </div>
      <div>
        Image <input type="file" name="image" />
      </div>
      <div>
        Last Name <input type="text" name="lastName" defaultValue="Doe" />
      </div>
      <div>
        Current Password{" "}
        <input type="password" name="currentPassword" defaultValue="password" />
      </div>
      <button
        type="submit"
        style={{ border: "1px solid gray", padding: "4px" }}
      >
        Submit
      </button>
    </form>
  )
}

export default Home

我们在这里处理表单数据

import path from "path"
import { writeFile } from "fs/promises"

export const POST = async (request: Request) => {
  const formData = await request.formData()

  // here we are getting form fields
  const lastName = formData.get("lastName")
  const firstName = formData.get("firstName")
  const image = formData.get("image") as File
  const currentPassword = formData.get("currentPassword")

  let file = {}

  // if image is present
  if (image?.name) {
    // then store the image on local
    const fileLocalPath = path.join(process.cwd(), `public/${image.name}`)
    const buffer = Buffer.from(await image.arrayBuffer())
    await writeFile(fileLocalPath, buffer)

    // file information
    file = {
      size: image.size,
      filepath: fileLocalPath,
      newFilename: image.name,
      type: image.type,
      lastModified: image.lastModified,
    }
  }

  return Response.json({ lastName, firstName, image: file, currentPassword })
}

它会给你这样的回应

Nextjs file upload response

© www.soinside.com 2019 - 2024. All rights reserved.