skip to Main Content

I am attempting to make my first MERN stack app and when I try to upload an image file my server is responding with the above error. In Payload it even lists that "name: post.png".

Please excuse my novice code as I am very new to JS and MERN.

Below is my component

import {useState} from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { toast } from 'react-toastify';

import './style.css';

export const FileUploader = ({onSuccess}) => {
const [file, setFile] = useState();
const [filename, setFilename] = useState('Choose file');
const onInputChange = (e) => {
setFile(e.target.files[0]);
setFilename(e.target.files[0].name)
};

const onSubmit = (e) => {
    e.preventDefault();
    const data = new FormData();
    data.append('file', file)
    data.append('name', filename)

    

    axios.post('http://localhost:8080/api/files', data)
        .then((response) => {
            toast.success('Upload Success')
            onSuccess(response.data)
        })
        .catch((e) => {
            toast.error('Upload Error')
        })
};

return(
    <><Link to="/">
        <button>
            Home
        </button>
    </Link>

    <form method="post" action="#" id="#" onSubmit={onSubmit}>
        <div className="form-group files">
            <label> {filename} </label>
            <input type="file"
                onChange={onInputChange}
                className="form-control"
                multiple="" />
        </div>

        <button>Submit</button>
    </form>
    </>
)

};

export default FileUploader;`

here is my files.js route:

const router = require("express").Router();
const { File, validate } = require("../models/file");



router.post("/", async (req, res) => {
    try{
        const { error } = validate(req.body);

        if (error)
            return res.status(400).send({ message: error.details[0].message });

        await new File({ ...req.body}).save();
        res.status(201).send({message: "File created successfully"})
    }
    catch (error){
        res.status(500).send({message: "Internal Server Error"})
    }
})

module.exports = router;

Thank you for any help, this is my first post here so please let me know if this formatting is poor for a question, thank you.

I tried editing the model schema and appending the filename to the data. I expected when I appended the filename to the data that it would be accepted by my server but it still gives me an error

2

Answers


  1. Chosen as BEST ANSWER

    Turns out I need to explicitly state the header overide so axios.post uses json:

    const onSubmit = (e) => {
        e.preventDefault();
        const data = new FormData();
        data.append("fileName", filename)
        //data.append(file, file)
        data.append("creator", "John")
        var object = {};
        data.forEach((value, key) => object[key] = value);
        var json = JSON.stringify(object);
        
    
        axios.post('http://localhost:8080/api/files', json, {
            headers: {'Content-Type': 'application/json'}
        })
            .then((response) => {
                toast.success('Upload Success')
                onSuccess(response.data)
            })
            .catch((e) => {
                toast.error('Upload Error')
            })
    };
    

  2. Axios is detecting that the object is Multipart/Form Data. You could use multer to handle the file upload. Multer will extract the file from the body of the request and then convert the rest of the body to json. You will be able to find the uploaded file in req.file

    It would look something like this:

    const multer = require("multer");
    const upload = multer({dest: "uploads/"});
    
    router.post("/", upload.single("file"), async (req, res) => {
      // do something with the file
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search