Search code examples
node.jsreactjsexpressmulter

Why is my React form being seen as application/json when I set it to multipart/form-data? The file I upload is being seen as undefined


I'm trying to upload an image file with React to my NodeJS backend but the file does not appear to be going over as multipart/form-data. I've set the form to be "multipart/form-data" but everytime I send it to my backend it is read as "application/json".

React Component with Form:

import axios from 'axios';
import React, { useContext, useState, useRef} from 'react';
import CollectionAPI from "../apis/collectionAPI";
import {CollectionContext} from '../context/collectionContext';

const AdminCreateC = (props) => {

    const{createItem, setCreateItem} = useContext(CollectionContext);

    const [images, setImages] = useState(null);

    //insures that the .env file is only run in a development environment and not a production environment
    if(process.env.NODE_ENV !== 'production'){
        //requires the the .env file configuration be run first hiding all info hidden via the .env file
        require('dotenv').config();
    }

    const handleSubmit = async (e) => {
        e.preventDefault()
        try{

            let formData = new FormData();
            formData.append('images', images);

            console.log(formData)
            axios.post("https://httpbin.org/anything", formData).then(res => console.log(res));

            const response = await CollectionAPI.post("/admin/create", {
                images: formData,
            })

            setCreateItem(response.data.data.newItem);

        }catch(err){
            console.log(err);
        }
    }

    return(
        <div>
             {/* The form enctype is set to multipart/form-data*/}
             <form action="/admin/create" method="POST" encType="multipart/form-data">
                  <div className="admin-form">
                       <label className="">Images</label>
                       <input  type="file" onChange={e => setImages(e.target.files[0])} name="images" className="form-control" required/>
                  </div>
             </form>
        </div>
    )
}

export default AdminCreateC;

NodeJS Route: (req.file appears to always be undefined)

//Create a collection item
router.post('/admin/create', upload.single('images'), async(req, res) => {
    try{
        const file = req.file;
        console.log("File: " + file);
    }catch(err){
        console.log(err);
    }
})

Solution

  • Axios post method has the default Content-Type of 'application/x-www-form-urlencoded'.

    You need to change that to multipart/form-data

    axios.post(
      "https://httpbin.org/anything", 
      formData, 
      {
        headers: {
          "Content-Type": "multipart/form-data"
        }
      })
      .then(res => console.log(res)
    );