1

I'm trying to send a image from a react front end to a node.js backend using axios, with help from this post: How do you send images to node js with Axios? I managed to get it from the frontend to the backend, but when I console.log the req.files and the req.body it's undefined or empty. I can't figure out how to fix it. Can anyone help me?

Here is the code for the app.js React frontend:

import "./App.css";
import React, { useState } from "react";
import axios from "axios";

function App() {
  const [image, setImage] = useState("");
  function handleImage(e) {
    console.log(e.target.files);
    setImage(e.target.files[0]);
  }
  function handleApi() {
    const formData = new FormData();
    formData.append("image", image);
    console.log(formData)
    axios
      .post("http://localhost:3001/users/editprofile/1", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      })
      .then((res) => {
        console.log(res);
      });
  }
  return (
    <div>
      <input type="file" name="file" onChange={handleImage} />
      <button onClick={handleApi}>submit</button>
    </div>
  );
}

export default App;

and this is the node.js back end:

router.post("/editprofile/:id", async (req, res) => {
  const id = req.params.id;
  console.log(req.files)
  console.log(req.body)
  //console.log(req)
  //const { pfp } = req.files;

  // if (pfp) {
  //   await pfp.mv(`${__dirname}/images/profile_pictures/pfp_${id}}`);
  // }

  //Would make the code "save" by not allowing any uploads at allz`
  //if (/^image/.test(image.mimetype)){
  //    console.log("not an image");
  //    return res.sendStatus(400);
  //}

  res.sendStatus(200);
});

When I log just the req I get a response to the Axios is sending something to the backend and when I look into the network and console in the browser I get the following things:

The network tab in the browser: enter image description here

The console in the browser: enter image description here

Thanks in advance for the help!!

Aleksandar
  • 844
  • 1
  • 8
  • 18
Tijmi
  • 45
  • 8
  • read the answer there: [_On node js server make sure to use some middle-ware which handles multipart requests. I used multer._](https://stackoverflow.com/a/44945988/4321299) – traynor May 01 '23 at 11:33
  • I treid to do that, but I don't unerstand it XD – Tijmi May 01 '23 at 15:10

1 Answers1

2

The problem is on the server side, you're missing a form/multipart request processing middleware.

The usual tool is multer

So, on your route, you need to add upload middleware, then you can access file via req.file (or req.files, if multiple files, check the docs).

Before that, you need to setup upload middleware where you setup location (destination), filename and mimetype checker.

Also, there you can read req.params.id and use it for filename, and also add image filter, not in the route.

Try this:

router:

const myUploadMiddleware = require('./upload');

router.post("/editprofile/:id", myUploadMiddleware, async (req, res) => {
  
  console.log('editprofile', req.body, req.file);

  res.sendStatus(200);
});

upload middleware:

const multer = require('multer');


const storage = multer.diskStorage({

    // my destination here
    destination: function(req, file, cb) {

        cb(null, `${__dirname}/images/profile_pictures/`)
    },
    // my custom filename here
    filename: function(req, file, cb) {

        //const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
        //cb(null, file.fieldname + '-' + uniqueSuffix)

        const id = req.params.id;

        cb(null, `pfp_${id}`);
    }
});

// my mimetype check here
const fileFilter = (req, file, cb) => {

    if (!file.mimetype.includes('image')) {
        return cb(new Error('not an image'));
    }
    cb(null, true);
};


// also field name here image has to correspond to image on the frontend
// formData.append("image", image);

const upload = multer({
    storage: storage,
    fileFilter
}).single('image');


module.exports = upload;
traynor
  • 5,490
  • 3
  • 13
  • 23
  • Thank you this helped!! the only problem I'm having now is that if I added a .jpg it won't go further in the code because of that it thinks it is a jpeg any solutions for that? ans it won't addd the file exxtention but `path.extname(file.originalname)` helps with that!! – Tijmi May 02 '23 at 13:35
  • yeah, you can tweak it depending on your needs. not sure what you mean, but you can check mimetypes, and create your whitelist, maybe something like this: [How to validate file extension with Multer middleware](https://stackoverflow.com/questions/60408575/how-to-validate-file-extension-with-multer-middleware) – traynor May 02 '23 at 15:46