简体   繁体   中英

req.file is undefined for multiple file uploads

I've read through all the possible answers here but I'm not sure anymore what the problem could be because none of them works. I have one form that uploads a single image and it works as expected but on a different form where I try and upload multiple files and have form inputs, the req.file is always undefined and the image data ends up in the req.body. So somewhere I think maybe there is an issue where multer is not getting the file data...?

I read in a couple of places that body-parser is possibly not playing well with multer but I unfortunately need them both.

route

const destination = './public/uploads/posts';
const storage = multer.diskStorage({
  destination: destination,
  filename: (req, file, cb) => {
    cb(null, file.originalname);
  },
});
const upload = multer({storage}).array('images');

router.post('/posts', (req, res) => {

  upload(req, res, (err) => {
    if(err) {
      console.log('errors', err)
      res.json({success: false, error: err})
    } else {
      if(req.files === undefined) {
        console.log('error: Images returned undefined');
      } else {
        const { title, description, url, auth_name, auth_id } = req.body;

        if(!title || !description) {
          return res.json({
            success: false,
            error: 'All fields required',
            message: 'Title and description fields are required'
          });
        }

        // path we store in the db
        let imageLocation = [];
        const post = new Post();

        for (const file of req.files) {
          imageLocation.concat('/uploads/posts/' + file.filename)
        }

        post.title = title;
        post.description = description;
        post.url = url;
        post.author_name = auth_name;
        post.author = auth_id;
        post.images = imageLocation;
        post.save((err, post) => {
          if(err) {
            return res.json({ success: false, error: err, message: 'post failed' });
          } else {
            return res.json({ success: true, message: "added new post", post: post });
          }
        });
      }
    }
  });
});

post in react component

My images are set in state which I get from the DropZone package (I tested without DropZone as well with same results. I made sure the the input name is "images"

submitNewPost = () => {
    const { title, description, url, images } = this.state;
    const auth_id = this.props.author_id;
    const auth_name = this.props.author_name;

    const formdata = new FormData();
    formdata.append('title', title);
    formdata.append('description', description);
    formdata.append('url', url);
    formdata.append('author_name', auth_name);
    formdata.append('author', auth_id);
    formdata.append('images', images);

    fetch('/api/posts', {
      method: 'POST',
      body: formdata
    }).then(res => res.json())
      .then((res) => {
        if (!res.success) {
          this.setState({ message: res.message });
        } else {
          this.setState({ 
              title: '', 
              description: '', 
              url: '', 
              images: '', 
              message: res.message 
          });
          socket.emit('newPost', res.post);
        }
      });
  }

UPDATE

With some help on this thread I managed to upload the images using my existing route and postman. When I test the route using my form, I still get an empty req.file and no uploads.

I added express-multipart-file-parser to my setup and I figure that is what brought me one step closer to fixing this.

Server

This is what I added to my server.js

 import { fileParser } from 'express-multipart-file-parser';
 app.use(fileParser({
  rawBodyOptions: {
      limit: '15mb',  //file size limit
  },
  busboyOptions: {
      limits: {
         fields: 20   //Number text fields allowed 
      }
  },
 }));

To properly populate req.files you need to use formdata.append like this:

images.forEach(image => {
  formdata.append('images', image);
})

You are missing to pass value with array.

router.post('posts', upload.array('image', 10), function (req, res, next) {

})

thanks for all the help. I managed to fix it. Turns out I was concatenating the FileList object to an array in my state so the structure was all wrong and at the server it just failed. My images upload perfectly now.

If I posted that part of my react component, I'm sure any of you would have picked up on that in a second, sorry. Did not occur to me that the problem was further up in my component.

THE PROBLEM

onFileLoad = (e) => {
  this.setState({
    images: this.state.images.concat(e.target.files)
  });
}

THE FIX

onFileLoad = (e) => {
  this.setState({
   images: e.target.files
  });
}

submitMediaPOst = () => {
  const imageArr = Array.from(images);
  imageArr.forEach(image => {
    formdata.append('images', image);
  });
...

for this issue not getting req.file in controller after upload middlewar, while testing in postman select multiple file in single property在此处输入图像描述 and ofcourse in front end append the files in a loop

   doc.forEach(file=> {
      formdata.append('file', file);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM