0

I have The Following ReactJS+HTML code :

import React, { useState } from 'react';

export const sendImage = () => {
  const [image, setImage] = useState();

  const handleSubmit = (e) => {
    e.preventDefault()
    let fileToUpload = image
    const formData = new FormData()
    formData.append('file', fileToUpload)
    
    fetch('/api/upload', {
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data',
          'Accept': 'multipart/form-data'
        },
        body: formData
      }).then(resp => {
        resp.json().then(data => {console.log(data)})
      })
    }


  return(
    <form onSubmit={handleSubmit} className="container mt-5 pt-5 pb-5" encType="multipart/form-data">

      <div className="form-inline justify-content-center mt-5">
        <label htmlFor="image" className="ml-sm-4 font-weight-bold mr-md-4">Image : </label>
        <div className="input-group">
          <input onChange={(e) => {setImage(e.target.files[0])}} type="file" id="image" name="file" accept="image/*" className="file-custom"/>
        </div>
      </div>

      <div className="input-group justify-content-center mt-4">
        <button type="submit" className="btn btn-md btn-primary">Upload...</button>
      </div>

    </form>
  )
}

And The Following Python-Flask code:

import os
from flask import Flask, request, render_template

app = Flask(__name__)


@app.route('/api/upload', methods=['POST'])
def handle_form():
    files = request.files
    file = files.get('file')
    """
      CODE TO HANDLE FILE
    """
    return jsonify({
        'success': True,
        'file': 'Received'
    })


@app.route("/")
def index():
    return render_template("index.html");   


if __name__ == "__main__":
    app.run(port=8080, debug=True)

The Problem is that when I Submit the form, the file doesn't get sent to the backend.

Respond when printing files & file from Python-Flask :

ImmutableMultiDict([])
None

How Can I fix This Issue?

Please Note :

When I use Plain HTML (non-React based form) It works out perfectly, but when using React based form it doesn't work.

2
  • Sorry if this is a stupid question, but have you tried submitting a normal, non-React based form to the same URL? Just to make sure that it's the python aspect that's wrong, rather than the React. Commented Aug 4, 2020 at 15:09
  • Yes, when I use a non-React based form Everything works out perfectly, but I want to use The React based form. Commented Aug 4, 2020 at 16:00

1 Answer 1

3

I would personally transition towards submitting the form in a different way. Consider doing it like this:

<form onSubmit={handleSubmit} className="container mt-5 pt-5 pb-5" enctype="multipart/form-data">
    <div className="form-inline justify-content-center mt-5">
        <label htmlFor="image" className="ml-sm-4 font-weight-bold mr-md-4">Image :  </label>
        <div className="input-group">
            <input type="file" id="image" name="file" 
            accept="image/*" className="file-custom"/>
        </div>
    </div>

    <div className="input-group justify-content-center mt-4">
        <button type="submit" className="btn btn-md btn-primary">Upload,,,</button>
    </div>
</form>
const handleSubmit = (e) => {
    e.preventDefault()
    const formData = new FormData(e.target);
    
    const Upload = async() => {
      await fetch('/api/upload', {
        method: 'POST',
        body: formData
      }).then(resp => {
        resp.json().then(data => {console.log(data)})
      })
    }
    Upload();
  }

This way, you're actually still using the browser-default Form system without having to reinvent any wheels, but it's still all within react and handled by a post request

I googled how to submit a formData with fetch api, and one article suggested not using the Content-Type header, so I stripped that out.

Alternatively, consider using axios:

          axios
            .post('/api/upload', formData)
Sign up to request clarification or add additional context in comments.

5 Comments

Thank You, I changed my handleSubmit function to match yours and removed Content-Type & Accept, and it worked perfectly.
cool, you didn't have to change to axios? interesting.
I actually made a little test project to see if I could send up the formData you did originally, controlling the image state in React code - and it worked! I did essentially the same thing you did, creating a brand new formData from scratch and appending the file to it. It might have only been the headers that were wrong for you in the end.
Can you post the code where you used this approach. I'll appreciate it.
the react code i used is in here, jsfiddle.net/qszxdyeh

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.