1

Im trying to upload an image (ReactJs) to my server (NodeJs+ Express+ multerJs) to digital Ocean.

Im using a POST Request with multipart/form-data;

I get a succesfull message from multerJs but I can see in the log on the server that the files: [] has an empty array. And that Digital Ocean didnt add any file of course.

When i do the same Post request with the form without handling the submission of the form ,everything is working and the Files array is not empty.the code above is working :

<form method="post" enctype="multipart/form-data" action="http://localhost:3004/upload_image_test_4"   >    </form>

Client-Side React.js :

export default class Select_size extends React.Component {
on_form_submit = (e) => {
    e.preventDefault();
    const fileInput = this.state.file;
    const formData = new FormData();
    formData.append('file', fileInput);
    const options = {
        method: 'POST',
        body: formData,
        headers: {
            'Access-Control-Allow-Origin': '*',
             Accept: 'application/json',
            'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
        }
    };
    var url =
        this.state.action_link +
        '?url=' +
        this.state.id_user +
        '/' +
        this.state.id_draft +
        '&name=' +
        this.state.name_file;
    fetch(url, options);
};

onChange = (e) => {
    this.setState({ file: e.target.files[0] });
};

 constructor(props) {
    super(props);
    this.state = {
  files: [],
  };
this.onChange = this.onChange.bind(this);
  }
render() {
    return (  
<form onSubmit={this.on_form_submit} enctype="multipart/form-data">
                    <input type="file" name="myImage" onChange={this.onChange} />
                    <button type="submit">Upload</button>
</form>

  )}

}

Server-side (Node.js/ ExpressJs/Multer/Digital Ocean) :

  const express = require('express');
  const router = express.Router();
  const bodyParser = require('body-parser');
  const aws = require('aws-sdk');
  const spacesEndpoint = new aws.Endpoint('fra1.digitaloceanspaces.com');
  const s3 = new aws.S3({
  endpoint: spacesEndpoint,
  accessKeyId: 'myID',
  secretAccessKey: 'MySecretKey'
  });
  const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: 'bucketName',
    acl: 'public-read',
    key: function(request, file, cb) {
        cb(null, urlBucket + name_image);
        }
   })
   }).array('upload', 1);

  router.post('/upload_image_test_4', function(request, response, next) {
  upload(request, response, function(error) {
    console.log(request, 'the request');
    if (error) {
        console.log(error);
        return response.json(error, 'error');
    }
    console.log('File uploaded successfully.');
    return response.json('success its uploaded to digital ocean');
});

});
module.exports = router;

If anyone can help me with that ! (I already 'googled' insanely,,,) Thanks !!

romain1304
  • 98
  • 3
  • 11
  • Can you create postman sample that works? – Oleg Nov 02 '19 at 13:35
  • yes with postman it works,,,, – romain1304 Nov 02 '19 at 16:37
  • Can you provide script by postman:https://learning.getpostman.com/docs/postman/sending-api-requests/generate-code-snippets/ – Oleg Nov 02 '19 at 16:48
  • Mistake, doesnt work with postman as well, a similar repository can be find here : https://github.com/nyinyi164/spaces-node-app it will work with
    upload but not with a post request made on axios or postman ,
    – romain1304 Nov 03 '19 at 02:02
  • Can you copy successful post details over browser with form : chrome dev network.. – Oleg Nov 03 '19 at 03:51
  • Yes of course, i couldnt add the details in the comment, here a pdf, thank you : https://storage1germany.fra1.digitaloceanspaces.com/9f54b16c69a77042b964423d4db9e3ac/52da9e3a467c62428b8058123a4cb80c/request%20with%20%3Cform%3E.pdf – romain1304 Nov 03 '19 at 04:49
  • And this is the details of the request with Postman : https://storage1germany.fra1.digitaloceanspaces.com/9f54b16c69a77042b964423d4db9e3ac/52da9e3a467c62428b8058123a4cb80c/request%20postman%20not%20working.pdf – romain1304 Nov 03 '19 at 05:01
  • can you click on view URL encoded in the request Form Data – Oleg Nov 03 '19 at 05:10
  • I clicked on it in the postman detail request, but formData is showing 'Formadata(0)' and it basically emtpy, so it doestn show anything more. But in the details of the working
    data request, 'FormData' is not showing in the detail request,,, weird.
    – romain1304 Nov 03 '19 at 05:22
  • I found a solution that I added in my post, thank you – romain1304 Nov 03 '19 at 06:59

3 Answers3

1

//EDIT I found a solution to my own question... on the github page dedicated to a bug related to Next.js : The file was not send to the request for some reasons. I used axios in this way and its now working :

React-js :

    sendFile = (e) => {
      const data = new FormData();
      const file = e.target.files[0];
      data.append('avatar', file);
     axios
            .post('http://localhost:3004/upload_test_stack_2', data)
            .then(console.log)
          .catch(console.error);  

      }

The server side (nodeJs) :

const upload = multer({
    storage: multerS3({
    s3: s3,
    bucket: 'My Bucket',
    acl: 'public-read',
    key: function(request, file, cb) {


        cb(null, file.originalname);
    }
    })

});

router.post('/upload_test_stack_2', upload.single('avatar'), (req, res) 
 =>      {

    console.log(req.file, 'The file appears here');
    return res.sendStatus(200);
      });
romain1304
  • 98
  • 3
  • 11
0

Files from input are not an array but FileArray, try [...e.target.files][0]

0

Related to Event Pooling in React and async behavior of setState.

Modify onChange handler:

Method 1:

Put the file to variable and set it in setState.

onChange = (e) => {

      const uploadFile = e.target.files[0] ;
      this.setState({ file: uploadFile  });
};

Method 2 with event.persist():

onChange = (e) => {
         e.persist();
         this.setState({ file: e.target.files[0] });
    };
Oleg
  • 3,580
  • 1
  • 7
  • 12