2

I am working on a react component where I want to upload a excel file to a server. Here is what I am trying. But it gives me an empty object when I console request body

<input type="file" id="avatar" name="avatar" onChange={this.fileHandler.bind(this)} style={{"padding":"10px"}}/>

Here is file handler method which will execute when input file changed:

fileHandler = (event) => {
        event.preventDefault();
        let fileObj = event.target.files[0];
        console.log(fileObj);
        //console.log(JSON.stringify(fileObj));

        var data = new FormData()
        data.append('file', fileObj)

        fetch("/upload", {
            method: 'POST',
            body: data
        }).then(function(response) {
            if (response.status >= 400) {
                throw new Error("Bad response from server");
            }
            return response.text();
        }).then(function(data) {
            console.log(data)
        }).catch(function(err) {
            console.log(err)
        });
}

Here is the server code to upload a file.

app.post('/upload', function(req, res) {
        console.log(req.body); // Output : {} or undefined
        /*try {
            if(!req.files) {
                res.send({
                    status: false,
                    message: 'No file uploaded'
                });

            } else {
                let avatar = req.files.avatar;

                //Use the mv() method to place the file in upload directory (i.e. "uploads")
                avatar.mv('./uploads/' + avatar.name);

                //send response
                res.send({
                    status: true,
                    message: 'File is uploaded',
                    data: {
                        name: avatar.name,
                        mimetype: avatar.mimetype,
                        size: avatar.size
                    }
                });
            }
        } catch (err) {
            res.status(500).send(err);
        }*/
     })

If I try below using form action it is giving me correct output in req.files but I don't want to redirect.

<form id="myForm" method="post" encType="multipart/form-data" action="/upload">
  <input type="hidden" name="msgtype" value="2"/>
  <input type="file" id="avatar" name="avatar" onChange={this.fileHandler.bind(this)} style={{"padding":"10px"}}/>
  <input type="submit" value="Upload" />
</form>

Also I don't want to use axios as I am using the same fetch request for all other execution. Any help is appreciated.

9
  • have you googled "Upload file using fetch()"? Commented Apr 9, 2020 at 12:13
  • I got this 1st result by doing so and it has everything well explained in it flaviocopes.com/how-to-upload-files-fetch Commented Apr 9, 2020 at 12:15
  • @ZohaibIjaz I am working on this since long time and I tried everything as per suggestion but no luck. Commented Apr 9, 2020 at 12:21
  • Have you tried the solution I mention in previous comment? Commented Apr 9, 2020 at 12:26
  • @ZohaibIjaz yes, the same I did as you can compare the code with the link you have posted but output is undefined Commented Apr 9, 2020 at 12:27

2 Answers 2

2

Finally, I am able to deal with the correct request parameters using fetch. Here is the solution which I tried and working as expected:

<form id="myForm" method="post" encType="multipart/form-data" action="/upload" onSubmit={this.fileSubmit.bind(this)}>
  <input type="hidden" name="msgtype" value="2"/>
  <input type="file" id="avatar" name="avatar" onChange={this.fileHandler.bind(this)} style={{"padding":"10px"}}/>
  <input type="submit" value="Upload" />
</form>

and here is the submit handler:

fileSubmit = (event) => {
  event.preventDefault();
  fetch(event.target.action, {
      method: 'POST',
      body: new FormData(event.target) // event.target is the form

  }).then((resp) => {
      return resp.json();
      //console.log(resp.json());

  }).then((body) => {
      // TODO handle body
      console.log(body);
      if(body.status) {
          alert(body.message);
      }
      else {
          alert("Please Select a file to upload");
      }
  }).catch((error) => {
      // TODO handle error
      //
  });

and on server side I am able to get req.files as well as the req.body.

app.post('/upload', function(req, res) {
        console.log(req.body); // which gives me form data
        console.log(req.files); // which gives me file object
});
Sign up to request clarification or add additional context in comments.

Comments

0

I really don't know what I am doing wrong with fetch but I achieved file upload by redirecting form's action to an invisible . Here I am able to prevent form redirect.

<iframe name="dummyframe" id="dummyframe" style={{"display": "none"}}></iframe>
<form id="myForm" method="post" encType="multipart/form-data" action="/upload" target="dummyframe">
  <input type="hidden" name="msgtype" value="2"/>
  <input type="file" id="avatar" name="avatar" onChange={this.fileHandler.bind(this)} style={{"padding":"10px"}}/>
  <input type="submit" value="Upload" />
</form>

So without fetch I am getting the file object at my server side like below:

app.post('/upload', function(req, res) {
        console.log(req.files); // Output : {avatar:{name:"", data: "", size:"", mimetype:""}}
})

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.