Python Flask
https://flask.palletsprojects.com/en/2.2.x/installation/
Create an environment
C:\flask_dev>py -3 -m venv venv
Activate the environment
C:\flask_dev>venv\Scripts\activate
Install Flask
venv C:\flask_dev>pip install Flask
C:\flask_dev\flaskreact\app.py
Install requirements
Flask-Cors
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
https://pypi.org/project/Flask-Cors/
(venv) PS C:\flask_dev\flaskreact>pip install -U flask-cors
(venv) PS C:\flask_dev\flaskreact>pip install Werkzeug
C:\flask_dev\flaskreact\app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #C:\flask_dev\flaskreact\app.py from flask import Flask, json, request, jsonify import os import urllib.request from werkzeug.utils import secure_filename #pip install Werkzeug from flask_cors import CORS #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors app = Flask(__name__) CORS(app, supports_credentials = True ) app.secret_key = "caircocoders-ednalan" UPLOAD_FOLDER = 'static/uploads' app.config[ 'UPLOAD_FOLDER' ] = UPLOAD_FOLDER app.config[ 'MAX_CONTENT_LENGTH' ] = 16 * 1024 * 1024 ALLOWED_EXTENSIONS = set ([ 'txt' , 'pdf' , 'png' , 'jpg' , 'jpeg' , 'gif' ]) def allowed_file(filename): return '.' in filename and filename.rsplit( '.' , 1 )[ 1 ].lower() in ALLOWED_EXTENSIONS @app .route( '/' ) def main(): return 'Homepage' @app .route( '/upload' , methods = [ 'POST' ]) def upload_file(): # check if the post request has the file part if 'files[]' not in request.files: resp = jsonify({ "message" : 'No file part in the request' , "status" : 'failed' }) resp.status_code = 400 return resp files = request.files.getlist( 'files[]' ) errors = {} success = False for file in files: if file and allowed_file( file .filename): filename = secure_filename( file .filename) file .save(os.path.join(app.config[ 'UPLOAD_FOLDER' ], filename)) success = True else : resp = jsonify({ "message" : 'File type is not allowed' , "status" : 'failed' }) return resp if success and errors: errors[ 'message' ] = 'File(s) successfully uploaded' errors[ 'status' ] = 'failed' resp = jsonify(errors) resp.status_code = 500 return resp if success: resp = jsonify({ "message" : 'Files successfully uploaded' , "status" : 'successs' }) resp.status_code = 201 return resp else : resp = jsonify(errors) resp.status_code = 500 return resp if __name__ = = '__main__' : app.run(debug = True ) |
Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.
https://www.postman.com/
upload
Post : http://127.0.0.1:5000/upload
Body - Form-data
Key : files[] - files
Value : select images
Create folder static\uploads
run (venv) C:\flask_dev\flaskreact>flask run
React JS
https://create-react-app.dev/
Create Project
C:\react-js>npx create-react-app myreactdev
Run
C:\react-js\myreactdev> npm start
C:\react-js\myreactdev\src\App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //C:\react-js\myreactdev\src\App.js import React, { Component } from 'react' ; import { BrowserRouter as Router, Route, Routes } from 'react-router-dom' ; import ImageUpload from './components/ImageUpload' ; import './App.css' ; class App extends Component { render() { return ( <Router> <Routes> <Route exact path= "/upload-image" element={<ImageUpload/>}/> </Routes> </Router> ); } } export default App; |
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save
Install Axios
https://www.npmjs.com/package/axios
C:\react-js\myreactdev>npm install axios --save
C:\react-js\myreactdev\src\components\ImageUpload.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | //C:\react-js\myreactdev\src\components\ImageUpload.js import React, { Component } from "react" ; import axios from "axios" ; export default class ImageUpload extends Component { constructor(props) { super(props); this.state = { image: "" , responseMsg: { status: "" , message: "" , error: "" , }, }; } // image onchange hander handleChange = (e) => { const imagesArray = []; for (let i = 0; i < e.target.files.length; i++) { this.fileValidate(e.target.files[i]); imagesArray.push(e.target.files[i]); } this.setState({ image: imagesArray, }); }; // submit handler submitHandler = (e) => { e.preventDefault(); const data = new FormData(); for (let i = 0; i < this.state.image.length; i++) { data.append( "files[]" , this.state.image[i]); } .then((response) => { console.log(response) if (response.status === 201) { this.setState({ responseMsg: { status: response.data.status, message: response.data.message, }, }); setTimeout(() => { this.setState({ image: "" , responseMsg: "" , }); }, 100000); document.querySelector( "#imageForm" ).reset(); } alert( "Successfully Uploaded" ); }) . catch ((error) => { console.error(error); if (error.response) { console.log(error.response) if (error.response.status === 401) { alert( "Invalid credentials" ); } } }); }; // file validation fileValidate = (file) => { if ( file.type === "image/png" || file.type === "image/jpg" || file.type === "image/jpeg" ) { this.setState({ responseMsg: { error: "" , }, }); return true; } else { this.setState({ responseMsg: { error: "File type allowed only jpg, png, jpeg" , }, }); return false; } }; render() { return ( <div className= "container py-5" > <div className= "row" > <div className= "col-lg-12" > <form onSubmit={this.submitHandler} encType= "multipart/form-data" id= "imageForm" > <div className= "card shadow" > {this.state.responseMsg.status === "successs" ? ( <div className= "alert alert-success" > {this.state.responseMsg.message} </div> ) : this.state.responseMsg.status === "failed" ? ( <div className= "alert alert-danger" > {this.state.responseMsg.message} </div> ) : ( "" )} <div className= "card-header" > <h4 className= "card-title fw-bold" > React-JS and Python Flask Multiple Image Upload with validation </h4> </div> <div className= "card-body" > <div className= "form-group py-2" > <label htmlFor= "images" >Images</label> <input type= "file" name= "image" multiple onChange={this.handleChange} className= "form-control" /> <span className= "text-danger" > {this.state.responseMsg.error} </span> </div> </div> <div className= "card-footer" > <button type= "submit" className= "btn btn-success" > Upload </button> </div> </div> </form> </div> </div> </div> ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //react-js\myreactdev\public\index.html <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "utf-8" /> <link rel= "icon" href= "%PUBLIC_URL%/favicon.ico" /> <meta name= "viewport" content= "width=device-width, initial-scale=1" /> <meta name= "theme-color" content= "#000000" /> <meta name= "description" content= "Web site created using create-react-app" /> <link rel= "apple-touch-icon" href= "%PUBLIC_URL%/logo192.png" /> <link rel= "manifest" href= "%PUBLIC_URL%/manifest.json" /> <title>React App</title> <link rel= "stylesheet" type= "text/css" href= "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" /> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id= "root" ></div> </body> </html> |
http://localhost:3000/