React fine-uploader upload the file - reactjs

I have a simple react app. I've added react-fine-uploader to it. I have a Flask server that accepts files and puts them into MongoDB database. The code for server looks like this:
from flask import Flask, render_template, request
from pymongo import MongoClient
import os
import time
from json import dumps, loads
app = Flask(__name__)
global index
map_dir = 'maps'
client = MongoClient(
'<connection_string>')
db = client.business
#app.route('/maps', methods=['GET'])
def process():
cursor = db.maps.find({}, {'_id': False})
maps = {'maps': []}
for doc in cursor:
try:
maps['maps'].append(doc['filename'])
except Exception:
pass
return dumps(maps)
#app.route('/map/<map_name>', methods=['GET'])
def get_map(map_name):
doc = db.maps.find_one({'filename': map_name}, {'_id': False})
return dumps(doc)
#app.route('/uploader', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
parsed = loads(f.read())
filename = ''.join(f.filename.split('.')[:-1]) + str(index) + '.json'
parsed['filename'] = filename
try:
result = db.maps.insert_one(parsed)
return 'File uploaded successfully'
except Exception:
return 'Error while uploading a file'
if __name__ == '__main__':
global index
index = len(os.listdir('maps')) + 1
app.run(debug=True)
It works with standard HTML input form with specifying target as localhost:5000/uploader. Now I want my fine-uploader form to do the same. In code it looks like this:
const uploader1 = new FineUploader({
options: {
request: {
endpoint: "localhost:5000/uploader"
},
resume: {
enabled: true
},
retry: {
enableAuto: true,
showButton: true
}
}
});
And somewhere in the render() method I got: <Gallery uploader={uploader1} />
Now I can select file, but when it is selected the form tries to upload it and it fails. Server is running and I can see no request on him in the terminal. Is there something I am doing wrong?
#Edit I've enabled debug mode and it throws something like this into dev console:
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https

Related

Problems with find_one_and_update using Pymongo/Flask with React application

I am working on the administrator part of a beginner's project I'm working on. I'm building in React.js with Pymongo/Flask connected to MongoDB Atlas for database storage. The page I'm working on allows the administrator to query the database to return all the users for a particular course they are taking or role they have (instructor or administrator). The returned data is mapped over to child components in React with a series of input fields using the defaultValue being populated by the props for the children (i.e. first name, last name, email, etc.). I'm saving new values to the child components' states and using JSON.stringify to make an axios.patch request. I'd like to be able to alter any user's information and submit it to the Mongo DB Atlas server, but am having some issues.
Here is what I think would be the necessary code from the front end:
saveChanges(id, data) {
var token = window.sessionStorage.getItem("token")
const updata = JSON.stringify(data)
axios.patch(`http://127.0.0.1:5000/update-instructor/${id}`, JSON.stringify({updata}), { headers: {"Authorization" : `Bearer ${token}`}})
.catch(error => {
console.log("There was an error with the patch request to instructor", error)
})
}
On the backend, this is the route that axios is calling:
#app.route('/update-instructor/<id>', methods=['GET', 'PATCH'])
def update_one_instructor(id):
id = ObjectId(id)
id_call = {"_id" : id}
updateObject = request.get_json(force=True)
instructors.find_one_and_update(id_call,
{ "$set" : { updateObject } },
return_document = ReturnDocument.AFTER)
The imports and setup of my flask/Pymongo:
import datetime
from distutils.log import error
import json
import pymongo
from bson.objectid import ObjectId
from bson import json_util
from flask_jwt_extended import create_access_token
from flask_jwt_extended import decode_token
from flask_jwt_extended import JWTManager
from flask_jwt_extended import jwt_required
from flask import Flask, jsonify, make_response, Response, request
from flask_cors import CORS, cross_origin
from pymongo import ReturnDocument
from werkzeug.security import generate_password_hash, check_password_hash
CONNECTION_URL = *connection url*
app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
cors = CORS(app)
app.config['JWT_SECRET_KEY'] = *secret key*
jwt = JWTManager(app)
try:
client = pymongo.MongoClient(CONNECTION_URL, serverSelectionTimeoutMS = 10000)
except:
print("Error - cannot connect to database")
Database = client.get_database(*database name*)
instructors = Database.instructors
I'm getting several issues. On the front end in Chrome, I am getting:
Access to XMLHttpRequest at 'http://127.0.0.1:5000/update-instructor/*string of ObjectID*' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
as well as:
PATCH http://127.0.0.1:5000/update-instructor/*string of ObjectID* net::ERR_FAILED
On the backend I'm getting a 400 error:
127.0.0.1 - - [14/Mar/2022 17:17:43] "OPTIONS /update-instructor/*string of ObjectID* HTTP/1.1" 400 -
Might be unecessary information here; but I'm not sure what is relevant. Any ideas on how I can get this patch request to go through and update MongoDB Atlas and, subsequently, the state in my parent component?
I found the solution. It seems it was an error in my Pymongo/Flask setup.
#app.route('/update-user/<id>', methods=['GET', 'PATCH'])
def update_one_user(id):
id = ObjectId(id)
updateObject = request.get_json()
jsonify(updateObject)
result = users.find_one_and_update({"_id" : id},
{ "$set" : updateObject },
return_document = ReturnDocument.AFTER)
return "User Updated"
I also did some refactoring, so the route is slightly changed. Basically it seems that using fewer variables as well as well as removing the {} from updateObject did the trick. But I also refactored my front end code to
saveChanges(id, data) {
let config = {
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*'
}
}
axios.patch(`http://127.0.0.1:5000/update-user/${id}`, JSON.stringify(data), config)
.catch(error => {
console.log("There was an error with the patch request to instructor", error)
})
}
It now includes some extra headers for CORS, but was was pointed out to me, it was the http 400 that was causing the CORS issue.

Can't get file from POST request using Flask and Bootstrap-Vue Form File Input

I'm trying to upload and image using Bootstrap-Vue Form File Input and send it to Flask Backend via POST using Axios library, then store in a folder.
My problem is that Flask can't find "file" in "request.files". Pretty sure I'm falling in a rookie mistake.
That's my code:
Frontend:
<template>
<div class="mx-5 container-fluid">
<div class="mx-5 row">
<div class="col-sm-10">
<b-form-file
type="file"
id="file"
v-model="file"
:state="Boolean(file)"
ref="file"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
v-on:change="submitFile"
></b-form-file>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
file: null,
};
},
methods: {
submitFile() {
/* Initialize the form data */
const path = 'http://localhost:5000/single-file';
const formData = new FormData();
/* Add the form data we need to submit */
formData.append('file', this.file);
/* Make the request to the POST /single-file URL */
axios.post(path,
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}).then(() => {
// console.log('SUCCESS!!');
})
.catch(() => {
// console.log('FAILURE!!');
});
},
},
};
Backend:
from flask import Flask, jsonify, request, send_file, redirect, url_for
from werkzeug.utils import secure_filename
import os
# configuration
DEBUG = True
UPLOAD_FOLDER = '/images'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
#app.route('/single-file', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
print('No file part')
return redirect(request.url)
file = request.files['file']
# If the user does not select a file, the browser submits an
# empty file without a filename.
if file.filename == '':
print('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('download_file', name=filename))
return ''
if __name__ == '__main__':
app.run()
I get HTTP code 302 (redirect) and print in console 'No file part'.
Any help would be very apreciated.
I can't see an obvious mistake in your code, it seems that the request is correctly passed through from your frontend and backend.
What I would suggest is to use Postman to decouple your frontend and backend in this case. If you get a correct response when using Postman, you can narrow down that the error is in the frontend, the browser, or something about axios which is meddling with the request data.
Also, try to get an error message, or print why flask thinks "file" isnt in request.files, it should be there if everything works as intended
I followed the response for Get the data received in a Flask request to get to the flask documentation for the Request class: Each key in files is the name from the <input type="file" name="">, which means that most likely you have to change 'file' from file = request.files['file'] to point to the actual filename that was selected from the file selection menu.

TFJS: loadGraphModel from HTTP server

I am implementing an object-detection web application using React and Tensorflow JS. I converted my model to a tensorflow JS model, such that I can load it into my React application. I want to load the model using a simple HTTP endpoint, which is a Flask server currently hosting on my local machine. The Flask main file looks as follows:
from flask import Flask
from flask_cors import CORS, cross_origin
import os
app = Flask(__name__)
cors = CORS(app)
#app.route('/')
def hello_world():
return 'Hello, World!'
#app.route('/model', methods=['GET'])
def get_modeljson():
"""
Get the model.json file and return it's contents.
"""
current_dir = os.getcwd()
file_path = os.path.join(current_dir, "models", "model.json")
with open(file_path, "r") as f:
return f.read()
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", threaded=True)
I have written a function in my React application that loads the graph model using the endpoint /model that is defined in the code above. The React function looks as follows:
import {useEffect, useState} from 'react';
import * as tf from '#tensorflow/tfjs';
import {loadGraphModel} from '#tensorflow/tfjs-converter';
function Model(props) {
const [model, setModel] = useState();
async function loadModel() {
try {
const model_url = "http://127.0.0.1:5000/model";
const result = await fetch(model_url);
const result_json = await result.json();
const model = await loadGraphModel(result_json);
console.log('model loaded...')
setModel(model);
console.log("Model correctly loaded");
} catch (err) {
console.log(err);
console.log("failed load model");
}
}
useEffect(() => {
tf.ready().then(() => {
loadModel();
});
}, []);
async function predictFunction() {
// use model to make predictions
}
return (
<Button onClick={() => {
predictFunction();
}}
/>
);
}
export default Model;
The FLASK API returns correctly the model.json file, however loadGraphModel returns the following error:
TypeError: url.startsWith is not a function
at indexedDBRouter (indexed_db.ts:215)
at router_registry.ts:95
at Array.forEach (<anonymous>)
at Function.getHandlers (router_registry.ts:94)
at Function.getLoadHandlers (router_registry.ts:84)
at Module.getLoadHandlers (router_registry.ts:110)
at GraphModel.findIOHandler (graph_model.ts:107)
at GraphModel.load (graph_model.ts:126)
at loadGraphModel (graph_model.ts:440)
at loadModel (Model.js:16)
I can not find any documentation about url.startsWith. Who sees what is going wrong here?
Going through the code I see a major issue with it, where you are trying to basically send a model.json from the backend to the frontend and then load the model from that model.json and perform inference on it. It would work but it is not efficient at all. Imagine having to do this a couple hundred times and I know the model.json file can be big in size. Instead there are two routes that you could go with:
Host the model on the backend, send the data to the backend through a POST request and then make predictions on the data from the request.
Use the model on the frontend and then make predictions on the input data from there.
There are some errors in the code which are causing the error but this is the issue that you need to fix first. If you could give me more information about the inputs you are working with I could draft up a workable solution.

React app not refreshing the log streamed through socket.io

In my project I am using flask_socketio as the server and socket.io-client with react as the client. My main.py(flask server) is constantly reading a log file(console.log) that is continuously updating. When the start button is clicked in the UI, the data of the log file is displayed, but as my log file is updated, the updated data is not displayed in the UI. I have to refresh the page or click the button again to see the updated data.
I want the data of the log file to live stream on the UI with a button click. How to fix this?
flask code
from flask import Flask, jsonify
# Needed for localhost testing.
from flask_cors import CORS, cross_origin
from flask_socketio import SocketIO, emit
from time import sleep
import pdb
import json
app = Flask(__name__)
# Socket io setup.
app.config['SECRET_KEY'] = 'secret!'
# |cors_allowed_origins| is required for localhost testing.
socket = SocketIO(app, cors_allowed_origins="*")
# For localhost testing.
CORS(app)
#socket.on('event_stream', namespace='/logConsole')
def test_connect():
def generate():
fname = "./src/console.log"
with open(fname) as f:
yield f.read()
emit_data = next(generate())
socket.sleep(0)
emit('custom-server-msg', {'data': emit_data})
if __name__ == '__main__':
socket.run(app)
React code
import React from 'react'
import io from 'socket.io-client'
class App extends React.Component {
state = { startVar: true, setVar: false };
setSocketListeners() {
let socket = io.connect('ws://localhost:5000/logConsole');
socket.emit('event_stream', () => {
console.log("Websocket connected: " + socket.connected)
})
socket.on('custom-server-msg', (data) => {
console.log("Data received: " + data.data)
const setup_logs = data.data;
this.setState({ setup_logs });
})
}
render() {
return (
<div className="App">
<h1>Data from log file</h1>
<button type="button" onClick={() => this.setSocketListeners()}>Start</button>
<p>{this.state.setup_logs}</p>
</div>
);
}
}
export default App;
This is how my browser console looks like-->
And this is my backend console-->
In your flask code, if you want to stream continuously, the next() needs to be called in a loop, now either that can be done by putting a infinite loop with a sleep time,
#socket.on('event_stream')
def test_connect():
def generate():
fname = "./src/console.log"
with open(fname, "r+") as f:
yield f.read()
while True:
emit_data = next(generate())
socket.sleep(2)
emit('custom-server-msg', {'data':emit_data})
or else, if the log file is too being updated continuously, os.stat(FILE_NAME).st_mtime can be used which will check the time stamp of the file being updated, and if any change is there in the log file, next() will be called to stream it:
#socket.on('event_stream')
def test_connect():
cached_stamp = 0
def generate():
fname = "./src/console.log"
with open(fname, "r+") as f:
yield f.read()
while True:
stamp = os.stat('./src/console.log').st_mtime
if stamp != cached_stamp:
cached_stamp = stamp
emit_data = next(generate())
emit('topo-server-msg', {'data':emit_data})

'Blueprint' object has no attribute 'config'

I am using flask-mail. But when i call the rest api in front end(react.js) of flask mail i am getting this error
'Blueprint' object has no attribute 'config'
Here is my code for flask mail
from flask import Flask,Blueprint
from flask_mail import Mail, Message
app = Blueprint('app', __name__)
app.register_blueprint(url_prefix='/api/v1/SalesLead')
mail=Mail(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'myvar30#gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(leadHistoryController)
#app.route("/")
def index():
msg = Message('Sheraspace', sender = 'myvar30#gmail.com', recipients = ['jobaer.jhs#gmail.com'])
msg.body = "Hello jh"
mail.send(msg)
return "Sent again"
if __name__ == '__main__':
app.run(debug = True)
Is there any solution for blueprint config? Or can i use the rest api in front end without using blueprint?
Must use flask.current_app instead.
from flask import current_app
def gen_file_name(filename):
"""
If file was exist already, rename it and return a new name
"""
fielname = current_app.config['UPLOAD_FOLDER']
return filename
There is similar question here
blueprint-config

Resources