Home > front end >  How to send data of a HTML form containing text and file in a single request to Flask app and store
How to send data of a HTML form containing text and file in a single request to Flask app and store

Time:07-29

I have to upload the form data which contains Text fields and Images and POST it to a flask app where I have to store text & images in the same collection. I am trying to send form data through axios.post() as application/json content type but the image can't be send as JSON and another problem is that how can I send Text entries of the form and file in the same entry but separately so it can be easily easily retrieved in flask app and stored in MongoDB

submit(e){
        e.preventDefault();
        axios.post('http://localhost:8103/api/db_create_post', { username: localStorage.getItem('username'), subject : this.state.subject, topic : this.state.topic, subtopic : this.state.subtopic, type: this.state.type, question : this.state.question, fact : this.state.fact, background : this.state.background, mcq1 : this.state.mcq1, mcq1opt1: this.state.mcq1opt1, mcq1opt2: this.state.mcq1opt2, mcq1opt3: this.state.mcq1opt3, mcq1opt4: this.state.mcq1opt4}, { "Content-Type": "multipart/form-data" })
        .then(response => {
            console.log(response.data);
            this.setState({postCreated : true});
            })
        .catch((error) => {
        console.log(error)
    });
    }
<form autoComplete="on" className={style.formPost} method="post" id="formPost" enctype="multipart/form-data" onSubmit={this.submit}>
            <div id='page1'>
            <div className={style.formNavigation}><a href="#page1" className={style.linkNext}><BsCaretLeftFill/></a> <a href="#page2" className={style.linkNext} onClick={this.pageVisible2}><BsCaretRightFill/></a></div>
            <span className={style.addPostFormHeading} >Select Category</span>
                <input list="subjects" name="subject" placeholder="Subject" form="formPost" value={this.state.subject} onChange={this.handleChange} required/>
                 <datalist id="subjects">
                    <option value="Computer Science"/>
                    <option value="Science"/>
                    <option value="Geography"/>
                    <option value="Pharmacy"/>
                    <option value="Accounts"/>
                    <option value="Economics"/>
                    <option value="Chemistry"/>
                    <option value="Physics"/>
                 </datalist>
                
                 <input list="topics" name="topic" placeholder="Topic" form="formPost" value={this.state.topic} onChange={this.handleChange} required/>
                 <datalist id="topics">
                    <option value="Computer Science"/>
                    <option value="Science"/>
                    <option value="Geography"/>
                    <option value="Pharmacy"/>
                    <option value="Accounts"/>
                    <option value="Economics"/>
                    <option value="Chemistry"/>
                    <option value="Physics"/>
                 </datalist>

                 <input list="subTopics" name="subtopic" placeholder="Subtopic" form="formPost" value={this.state.subtopic} onChange={this.handleChange} required/>
                 <datalist id="subTopics">
                    <option value="Computer Science"/>
                    <option value="Science"/>
                    <option value="Geography"/>
                    <option value="Pharmacy"/>
                    <option value="Accounts"/>
                    <option value="Economics"/>
                    <option value="Chemistry"/>
                    <option value="Physics"/>
                 </datalist>

                 <input list="type" name="type" placeholder="Type" form="formPost" value={this.state.type} onChange={this.handleChange} required/>
                 <datalist id="type">
                    <option value="News"/>
                    <option value="Information"/>
                    <option value="News & Information"/>
                 </datalist>
                 </div>

                 <div id="page2">
                 <div className={style.formNavigation}><a href="#page1" className={style.linkNext} onClick={this.pageVisible1}><BsCaretLeftFill/></a> <a href="#page3" className={style.linkNext} onClick={this.pageVisible3}><BsCaretRightFill/></a></div>
                    <span className={style.addPostFormHeading}>Create Post</span>
                    <input type="text" form="formPost" name="question" placeholder="Question (optional)" size="50" value={this.state.question} onChange={this.handleChange}/>
                    <textarea type="text" form="formPost" name="fact" placeholder="Fact (required)" maxLength="500" cols="50" rows="7" value={this.state.fact} onChange={this.handleChange} required/>
                 </div>
                 <div id="page3">
                 <div className={style.formNavigation}><a href="#page2" className={style.linkNext} onClick={this.pageVisible2}><BsCaretLeftFill/></a> <a href="#page4" className={style.linkNext} onClick={this.pageVisible4}><BsCaretRightFill/></a></div>
                 <span className={style.addPostFormHeading}>Select Background</span>
                    <span className={style.mediaUploadOptions}>
                        <a href="#selectMedia" onClick={this.mediaUploadTypeSelectMedia}>Select Media</a>
                        |
                        <a href="#uploadMedia" onClick={this.mediaUploadTypeUploadMedia}>Upload Media</a>
                    </span>
                    <div className={style.selectMedia} id="selectMedia">
                        <form action="" id="searchBackground">
                        <input name="search" type="search" placeholder="Enter Background" form="searchBackground" />
                        <input type="submit" value="Search"/>
                        </form>
                    </div>
                    <div className={style.uploadMedia} id="uploadMedia">
                    <input type="file" name="background" value={this.state.background} onChange={this.handleChange} form="formPost" accept="image/*" required/>
                    </div>
                 </div>
                 <div id="page4">
                 <div className={style.formNavigation}><a href="#page3" className={style.linkNext} onClick={this.pageVisible3}><BsCaretLeftFill/></a> <a href="#page4" className={style.linkNext} onClick={this.pageVisible4}><BsCaretRightFill/></a></div>
                 <input type="hidden" name="custId" value=""/>
                    <input type="text" name="mcq1" placeholder="Ask a Question" form="formPost" size="50" value={this.state.mcq1} onChange={this.handleChange} required/>
                    <input name="mcq1opt1" type="text" placeholder="Option 1" form="formPost" size="40" value={this.state.mcq1opt1} onChange={this.handleChange} required/>
                    <input name="mcq1opt2" type="text" placeholder="Option 2" form="formPost" size="40" value={this.state.mcq1opt2} onChange={this.handleChange}required/>
                    <input name="mcq1opt3" type="text" placeholder="Option 3" form="formPost" size="40" value={this.state.mcq1opt3} onChange={this.handleChange}/>
                    <input name="mcq1opt4" type="text" placeholder="Option 4" form="formPost" size="40" value={this.state.mcq1opt4} onChange={this.handleChange}/>
                    <input type="submit" value="Submit"/>
                 </div>
            </form>

CodePudding user response:

Axios POST by default send data as applicaiton/json, which doesn't support sending files as binary. There are two recommended solutions.

  1. Send your file encoded as base64. Example here.
  2. Send your data as multipart/form-data. Example here.

Note that both approaches require adjustments in your backend. In approach 1 you'll need to check for uploaded files in request.files. In approach 2 you'll be required to decode the base64 back to binary.

CodePudding user response:

So guys in tech world their are multiple ways to do a thing and that's what increases cognitive load. I tried to do things with FETCH & AXIOS, with and without form data, then I tried filereader API, automatic data transfer but nothing worked for me. Now here is the solution

submit(e){
        e.preventDefault();
        const form_data= new FormData();
        const ABC= document.querySelector('#uploadMedia > 
`enter code here`input[type="file"]').files[0];
        form_data.append('username', localStorage.getItem('username'));
        form_data.append('subject', this.state.subject);
        form_data.append('topic', this.state.topic);
        form_data.append('subtopic', this.state.subtopic);
        form_data.append('type', this.state.type);
        form_data.append('question', this.state.question);
        form_data.append('fact', this.state.fact);
        form_data.append('background', ABC);
        form_data.append('mcq1', this.state.mcq1);
        form_data.append('mcq1opt1', this.state.mcq1opt1);
        form_data.append('mcq1opt2', this.state.mcq1opt2);
        form_data.append('mcq1opt3', this.state.mcq1opt3);
        form_data.append('mcq1opt4', this.state.mcq1opt4);
        axios({method: "post", url: "http://localhost:8103/api/db_create_post", 
data: form_data, headers: { "Content-Type": "multipart/form-data" }})
        .then(response => {
            console.log(response.data);
            this.setState({postCreated : true});
            })
        .catch((error) => {
        console.log(error)
    });
    }

By this you can send StringField & FileField data. And so easily extract it in your react app using request.form & request.files and to insert it in MongoDB database using MongoEngine ODM you simply have to pass request.form while creating the object of the ODM class and later put the image on the object. here's the code

'''
def db_create_post():
    image=request.files['background']
    formData=request.form
    PostObj(formData).create_a_post(image)
    return "Post Stored Successfully in post database", 200
'''

Although I have created a subclass and passed the image as an argument of the method of the class and the form data in the Object.

  • Related