Sending image from html canvas to flask python not working - javascript

I am trying to make a flask app with html and js. It takes image from webcam, stores in html canvas, and then convert canvas to data url and send it to flask via ajax. I than use base64 to decode the data and read it with cv2 imdecode.
The problem I am having is my python code of the image is not executing at all. My webpage loads, everything works but when I take the pic, nothing happens.
Also another thing is that the console.log function of JS doesn't work when html is rendered in flask, so I don't know if something is wrong with my JS code.
Can you please look at my html as well as python code to tell me where I am going wrong? I am sure that the python function supposed to be called on the url of ajax is not called.
This is my js for sending the ajax:
//Function called on pressing a html button
function takePic() {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);//video is the video element in html which is recieving live data from webcam
var imgURL = canvas.toDataURL();
console.log(imgURL);
$.ajax({
type: "POST",
url: "http://url/take_pic", //I have doubt about this url, not sure if something specific must come before "/take_pic"
data: imgURL,
success: function(data) {
if (data.success) {
alert('Your file was successfully uploaded!');
} else {
alert('There was an error uploading your file!');
}
},
error: function(data) {
alert('There was an error uploading your file!');
}
}).done(function() {
console.log("Sent");
});
}
I have question about the url parameter in ajax, I think something specific must come before that"/take_pic", not just "https://url".
Here is my python:
from flask import Flask,render_template,request
import numpy as np
import cv2
import re
import base64
import io
app = Flask(__name__,template_folder="flask templates")
#app.route('/')
def index():
return render_template('live webcam and capture.html')
#app.route('/take_pic',methods=["POST"])
def disp_pic():
data = request.data
encoded_data = data.split(',')[1]
nparr = np.fromstring(encoded_data.decode('base64'), np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow(img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
app.run(debug = True)

I just created new python and html files and put similar code and now it is working. Don't know the exact cause of error but both the codes are same.

Related

How to save raw HTTP POST data using ajax and Python CGI

Is it even possible? Im trying to do something like this
function sendToServer(){
var jsonObj = {ip: ip, port: port, stime: stime, maxsamples: maxsamples, dplaces: dplaces};
var jsonStr = JSON.stringify(jsonObj);
console.log(jsonStr);
console.log(jsonObj);
$.ajax({
url: url,
type: "POST",
data: jsonStr,
dataType: "json",
success: function (response){
console.log(response)
},
error: function (xhr,status,error){
alert(error.message);
alert(error.response);
}
});
};
I have no problem with retrieving the data in Python file. I can even modify it and get modified response. But if i try to save what i send I get an error saying "undefined". Both browsers Firefox and Chromium are saying that's error 500.
#!/usr/bin/python3
import cgi, cgitb
import json
import sys
import os
content_len = int(os.environ["CONTENT_LENGTH"])
req_body = sys.stdin.read()
myjson = json.loads(req_body)
# data modification
myjson["ip"] = "do sth"
print('Content-Type: application/json\r\n\r\n')
# 2 troublesome lines
open with("config.json", "w") as file:
file.write(myjson)
print(json.dumps(myjson))
I don't know what am I missing. I guess with flask it would be easier but I need to try it like this. Thanks in advance
It came out that the owner and group of the folder where files were, was wrong. Server should be the owner. So scripts are correct they work properly everything I had to do was type chown in console:/

Flask: Passing data from AJAX to a render_template() call, redirecting/refreshing the page with parameters

This issue comes down to the fact that I haven't yet figured out how to pass data from javascript to Flask/Python via AJAX in the right way.
I have built a Flask application that uses JsPsych as a javascript/front-end framework for an online experiment. jsPsych allows you to create a handler function, on_finish(), that executes once the experiment is finished.
I wanted my experiment's data to be stored on the backend, and that was supposed to be the end o the experiment. I created a function called data_to_csv() that was mounted to the url /temp_storage, that did this. Then I created another url endpoint for /experiment_end, which displays a simple html page stating that the experiment is over and data was saved.
jsPsych.init({
...
on_finish: function() {
var subj_id = jsPsych.data.get().select('user_id').values[0];
var test_trials_collection = jsPsych.data.get();
var test_trial_json = test_trials_collection.json();
$.ajax({
type: "POST",
url: "/temp_storage",
data: {experiment_data:test_trial_json, webapp_id:subj_id},
success: function(response) {
window.location.href="/experiment_end";
},
error: function(xhr, textStatus, thrownError) {
alert('An error occurred while trying to save data');
console.log(thrownError);
}
});
},
});
The Flask side/the code for /temp_storage looked like...
#app.route('/temp_storage', methods=['GET', 'POST'])
def data_csv_func():
test_trial_json_obj = request.form['experiment_data']
subj_id = request.form['webapp_id']
test_trial_json_obj = json.loads(test_trial_json_obj)
df_data = pd.DataFrame(test_trial_json_obj)
csv_name = "app_dir/static/textdata/" + "appid_" + str(subj_id) + ".csv"
df_data.to_csv(csv_name)
return "Experiment is over!"
#app.route('/experiment_end', methods=['GET', 'POST'])
def show_qualtrics_after_experiment():
return render_template("end.html")
But now I don't want the AJAX call to simply end my experiment. I want my AJAX call to lead to a new webpage within the Flask application that contains a survey, take_qualtrics.html. I also need take_qualtrics.html to have, at the very least, the webapp_id string passed into it (but it would be ideal if I could also pass in the json object for jspsych's data, i.e. test_trials_json_obj). This is in order to link survey responses and web app experiment data
I initially just tried replacing the return statement in data_csv_func() to return render_template("take_qualtrics.html", data={"webapp_id":subj_id, "experiment_data":test_trial_json_obj}), and I deleted/commented out the windows.href("/experiment_end") call. I kept the AJAX call as is (the url was still /temp_storage), I found that this would execute data_to_csv() but the render_template() call wouldn't actually redirect my web page to another url.
So it seems like an AJAX call to a Flask function can't actually trigger redirects on the user's side. And I'm not sure how to work around this currently. I want to have some way of loading take_qualtrics.html and passing it the webapp id (created in javascript) as an argument.

Continuously check if file exists with AJAX in Django

I've developed an application in Django where a user goes to a form on a site and enters in an Elasticsearch query, then generating a report for the user to download. It all works fine and dandy, but lately in testing some more queries we've noticed that some return a lot of results which leads to a timeout request.
What we've figured out that we'd like to do is have Django continuously check if a file exists (because it won't be written to the local system until it's completed) to prevent that timeout issue. Additionally, once the file is done being created we want to add a download button so that the user knows it is done.
Following this tutorial, I added a function to my views.py and associated it with a url which is then called by a javascript code block in my html form. Because I am brand new to using AJAX, JQuery, Javascript, and Django I'm not quite sure how to get it to work. Mainly, I'm trying to figure out how to get it to keep checking if the file is done being created yet. If this were just using basic Python I would do a while loop but I'm unclear how to translate that to JavaScript.
views.py
def check_progress(request):
"""
Returns whether document generation is complete or in progress
Returns 0 for in-progress, 1 for complete (either due to completion, or error)
"""
# check if file exists, return response as a JSON
file = "/report.docx"
data = {
"file_created": path.exists(file)
}
return JsonResponse(data)
urls.py
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.get_query, name='form'),
path('^ajax/check_progress/$', views.check_progress, name='check_progress')
] + static(settings.STATIC_URL, document_root=settings.STAT)
form.html
{% block javascript %}
<script>
$("#id_username").change(function () {
var username = $(this).val();
$.ajax({
url: '/ajax/check_progress/',
type: 'HEAD',
data: {
'file_exists': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("This file is not yet created");
}
}
});
});
</script>
{% endblock %}
You can use setInterval to continually make requests to your backend to see if the file is complete. When it has finished the file, you clear the interval.
var checkInterval = setInterval(isFileComplete, 10000); //10000 is 10 seconds
function isFileComplete() {
$.ajax({
url: '/ajax/check_progress/',
type: 'HEAD',
data: {
'file_exists': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("This file is not yet created");
//add your own flag here to stop interval
clearInterval(checkInterval);
}
}
});
}
You can use setTimeout to run your Ajax request at regular intervals

Execute python script -- Ajax and Flask

I apologize if this is unclear or anything like that. I'm very very new to web programming of any kind, so please be patient. When a link is clicked, I want to run a python script and then display the results. What is currently happening is it's just returning the HTML page. I have an idea of why but no clue how to fix it. I believe the issue is with the Flask python code, but please any input is appreciated. I will comment the area I believe to be the problem
Flask (Python) code:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def index():
return "Hello, world!"
#app.route('/cgi-bin/cputemp.py', methods=['GET', 'POST'])
#this is where need to put something, but I don't know what.
#Without defining this route I was getting a 405 error. I have no idea
#what would go here -- this is just the directory to the python and I
#thought the routes were for different web pages the user could access.
#Again, I believe *this* is the source of the problem. Obviously
#right now it's just returning the HTML of the following test() function.
#app.route('/test', methods=['GET', 'POST'])
def test():
return render_template("test.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
test.html
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="/static/test.js"></script>
<div id="swiss">Click to display CPU Temp</div>
</html>
test.js
function cputemp2()
{
$.ajax(
{
type: "POST",
url: "cgi-bin/cputemp.py",
dataType: "html",
success: function(msg)
{
console.log(msg); # It's just returning the HTML of test.html currently
document.getElementById('swiss').innerHTML = msg;
},
});
}
cputemp.py
#!/usr/bin/python
import cgi;
import cgitb;
import time
cgitb.enable()
import commands
import sys
import string
print "Content-type: text/html\n\n";
mytemp1 = commands.getoutput('/opt/vc/bin/vcgencmd measure_temp | cut -d "=" -f2 | cut -f1')
output = "Pi CPU Temp is: " + mytemp1
print output
My question is -- I thought the AJAX code in the test.js file would be handling the call to the python script. All it does is execute the method below the route to that directory in my Flask code. So do I need to run the python code there? How do I do this?
Thank you so much, I'm really lost and stuck on this.
There are a few things here that need to be fixed to get things working (or at least how I understand you want them to work).
If you're going to be using Flask, you don't need the route to point to a Python script. You can route to something like /cputemp and then run a function that returns the piece of HTML with the CPU temp that I presume you wanted to display.
#app.route('/cputemp', methods=['GET', 'POST'])
def cputemp():
mytemp1 = commands.getoutput('/opt/vc/bin/vcgencmd measure_temp | cut -d "=" -f2 | cut -f1')
return render_template("cputemp.html", temp=mytemp1)
Don't forget to import commands at the top. Although, you really should be using subprocess instead. https://docs.python.org/2/library/commands.html
The return there uses a Flask template to create the HTML fragment that you want to insert when the AJAX request is successful. http://flask.pocoo.org/docs/0.11/quickstart/#rendering-templates
For example, cputemp.html can simply be something like:
<p>Pi CPU Temp is: {{ temp }}</p>
Note that I don't know whether that command being assigned to mytemp1 works. That's a separate issue from not being able to display the information you want.
Now for the AJAX part. I added an error handler to help debug further issues. Note that I changed the URL to match the route. Also, using innerHTML has security issues, and rather than concerning yourself with sanitizing what you set innerHTML to, use jQuery's html function. http://api.jquery.com/html/
function cputemp2() {
$.ajax({
type: "POST",
url: "/cputemp",
dataType: "html",
success: function(msg) {
console.log(msg);
$("#swiss").html(msg);
},
error: function (xhr, status, error) {
console.log(error);
}
});
}
Hope this is enough to get you moving along.

Jquery get Request Uri too long

I have a project which is built on ASP.NET MVC. There is a database table to store user's details including image, an api to output his details and view where i consume the api by ajax call. My api is returning the base64 value of image perfectly, but a 404 error comes saying request uri too long when i try to display the image.
Relevant lines of code are
$.ajax({
url: // url of api,
type: "GET",
success: function (data) {
var preview = document.querySelector('img');
preview.src = data.Image;
}
})
Does your base64-string start with data:image/png;base64,?
Look here for complete example.

Categories