Search code examples
reactjsnext.jsmultipartform-dataformidable

Upload input form data and file/image Next js


I am trying to send form data life person name, email and image together using Next js. I used formdata for file upload and using react-hook-form for form input. The problem is I couldn't receive the image/file in the Next api.

My codes are :

Onchange:

const handleImgChange = (e) => {
    if (e.target.files && e.target.files[0]) {
        const img = e.target.files[0];
        setProfileImg(img);
    }
};

to get form data from input.

const handleIChange = (e) => {
    const value = e.target.value;
    setContents((prevContnet) => {
        return {
            ...prevContnet,
            [e.target.name]: value,
        };
    });
};

On submit

const handleOnsubmlit = (e) => {
    e.preventDefault();
    if (profileImg.length > 0) {
        const formData = { ...contents, profile_picture: profileImg };
        updateUserSetting(formData);
    } else {
        updateUserSetting(contents);
    }
};

updateUserSetting

async function updateUserSetting(formdata) {
    try {
        console.log("form datas", formdata);
        dispatch({ type: "UPDATE_USER_SETTING_REQUEST" });
        const { data } = await axios(
            `${NEXT_URL}/api/updateusersetting`,
            {
                method: "PUT",
                formdata,
                "content-type": "multipart/form-data",
            }
        );
        console.log("return data ", data[0]);
        dispatch({ type: "UPDATE_USER_SETTING_SUCCESS", payload: data[0] });
    } catch (error) {
        dispatch({
            type: "UPDATE_USER_SETTING_FAIL",
            payload: error.response 
        });
    }
}

API

import { IncomingForm } from "formidable";

 export const config = {
     api: {
         bodyParser: false,
     },
 };

export default async (req, res) => {
    if (req.method === "PUT") {
        if (!req.headers.cookie) {
            res.status(403).json({ message: "Not Authorized" });
            return;
        }
        const { token } = cookie.parse(req.headers.cookie);

        console.log("body is", req.body);

        const formData = await new Promise((req, res) => {
            const form = new IncomingForm();
            form.parse(req, (err, fields, files) => {
                if (err) {
                    next(err);
                    return;
                }
                res.writeHead(200, { "content-type": "multipart/form-data" });
                res.json({ fields, files });
            });
        });
};

how can I put data together and send it to the desired API? Thanks in advance.


Solution

  • You can use the FormData interface to send files and other fields as a single JSONified string, or individual strings. Formidable will separate your fields and files in the callback, and you can process them individually.

    Here's a working Codesandbox.

    Output:

    enter image description here