1

I'm trying to upload multiple files with React/express and multer. But can't find what's wrong in my code...(I tried many solutions that I found here but I can't see where I'm wrong). Here is my code :

**Front : **

    function App() {
  const [file, setFile] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const formData = new FormData();
    let newArr = [];
    for (let i = 0; i < file.length; i++) {
      newArr.push(file[i]);
    }
    formData.append('monfichier', newArr);

    console.log(formData.get('monfichier'));

    axios
      .post('http://localhost:3000/uploaddufichier', formData)
      .then((res) => res.data);
  };

  return (
    <div className='App'>
      <form
        onSubmit={handleSubmit}
        method='POST'
        encType='multipart/form-data'
        action='uploaddufichier'
      >
        <input
          type='file'
          name='monfichier'
          onChange={(e) => setFile(e.target.files)}
          multiple
        />
        <button> envoyer </button>
      </form>
    </div>
    enter code here

BACK

const multer = require('multer');
const fs = require('fs');
const cors = require('cors');
const path = require('path');
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'file-storage');
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now());
  },
});
const upload = multer({ storage: storage });

app.use(express.json());
app.use(router);
app.use(cors());
app.use('/file-storage', express.static('file-storage'));
app.use(function (err, req, res, next) {
  console.log('This is the invalid field ->', err.field);
  next(err);
});

app.post(
  '/uploaddufichier',
  upload.array('monfichier'),
  function (req, res, next) {
    console.log(req.files);
    fs.rename(
      req.files.path,
      'file-storage/' + req.files.originalname,
      function (err) {
        if (err) {
          res.send('problème durant le déplacement');
        } else {
          res.send('Fichier uploadé avec succès');
        }
      }
    );
  }
);

For now the back-end console.log(req.files) return an empty array... And the front-end console.log(formData.get('monfichier') return [object File], [object File] IF anyone could help me for that issue....It'll be glad :)

6
  • I think you should use formData.append('monfichier['+i+']', file[i]); for each of the files within the loop. Commented Jan 3, 2021 at 10:38
  • With your current code, did you check the value of req.file (instead of req.files)? Commented Jan 3, 2021 at 10:50
  • @alexis_thual : Still undefined, node return : TypeError [ERR_INVALID_ARG_TYPE]: The "oldPath" argument must be of type string or an instance of Buffer or URL. Received undefined at Object.rename (fs.js:726:13) Commented Jan 3, 2021 at 10:59
  • @Molda : Same issue, still an empty array so req.files.path is undefined... Commented Jan 3, 2021 at 11:01
  • Is there a reason for creating a new array instead of doing formData.append('monfichier', file);? Commented Jan 3, 2021 at 11:13

2 Answers 2

5

A small tweak would have fixed it let me fix it and highlight the tweak that will fix it below.

function App() {
  const [file, setFile] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const formData = new FormData();
    let newArr = [];
    //********* HERE IS THE CHANGE ***********
    for (let i = 0; i < file.length; i++) {
      formData.append('monfichier', file[i]);
    }
    

    console.log(formData.get('monfichier'));

    axios
      .post('http://localhost:3000/uploaddufichier', formData)
      .then((res) => res.data);
  };

  return (
    <div className='App'>
      <form
        onSubmit={handleSubmit}
        method='POST'
        encType='multipart/form-data'
        action='uploaddufichier'
      >
        <input
          type='file'
          name='monfichier'
          onChange={(e) => setFile(e.target.files)}
          multiple
        />
        <button> envoyer </button>
      </form>
    </div>

The array method on multer accepts multiple files over the wire provided they have the corresponding name you specified (in our case 'monfichier'). So what we have done with the for-loop on the front-end is append several files with the same name - monfichier.

This question has been unanswered for 9months but hopefully, it will be helpful to you or anyother person that is facing this blocker. #cheers

Sign up to request clarification or add additional context in comments.

2 Comments

I cannot explain how happy I am right now. I was stuck 3 freaking hours on this and i tried every trick up my sleeve and it did not work. Thanks a lot, friend!
Most Obliged my friend
2

I know this is an old question, however, this solution will be useful to anyone who is experiencing a similar challenge.

The solution is simple. You must attach your photos with the same name on the frontend. then sending them to the backend. The rest will be handled by Multer, and you can access your files via 'req.files'.

Example

React

const formData = new FormData();
    for (let i = 0; i < event.target.files.length; i++) {
      formData.append("images", event.target.files[i]);
    }
    fetch("http://localhost:3003/api/v1/upload", {
      method: "POST",
      body: formData,
    });
  };

Backend - ExpressJs + Multer

gallaryRouter
  .route("/:galleryId")
  .post(
    UploadGallery.array("images"),
    (req,res)=>{console.log(req.files)}
  ) 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.