I want to change an image when I click on it with an image from another drive. For this I created this python function:
#main.route('/tester/', methods=['GET', 'POST'])
def tester():
if request.method == "GET":
test_img = "D:\TBV_Data\MS_CO_Front_20120403_140154_0001140_006.png"
return send_file(test_img, mimetype='image/png')
I request this data by the following function:
function testFunc() {
$.ajax({
url: '/tester', //server url
type: 'GET', //passing data as post method
async: false,
success: function(data) {
$("#myimage9").attr("src", "data:image/png;base64," + data);
},
});
};
The outcome of the "src" of the image is, unfortunately, a load of weird data:
<img id="myimage9" src="data:image/png;base64,�PNG
IHDR�I!�IDATx���mK�&�}�;��morg��c�V��)C�� B��.�(z�� ��� ��*��B�y2�I��^~��]D�1��ÁDb�9��&�E����o-���OZl��/_���NJ��%�%�т���6�ݴw�~��EE���-�[p�z^3Y����8��#�
I can imagine that I didn't encode the image correctly. Could somebody please tell me what I am doing wrong?
EDIT:
I tried to encode the data to base64 with:
function utoa(str) {
return window.btoa(unescape(encodeURIComponent(str)));
};
This will unfortunately just changes the data to the following, but will not show the image:
<img id="myimage9" src="data:image/png;base64,/VBORw0KGgoAAAANSUhEUgAABRAAAAP9CAIAAAAUSSH9AAEAAElEQVR4/f397m1L/Sb9ff0OO/39bW9yZ/39Y/0dVv39KUP9/SBC/f0u/Sh6A
On the server side, add a filename variable to your route:
import os
from flask import request, send_from_directory
IMAGE_DIR = r"D:\TBV_Data"
#main.route('/tester/<filename>')
def tester(filename):
return send_from_directory(IMAGE_DIR, filename)
This uses the send_from_directory function to make sure that the client cannot download files from outside the designated directory by entering filenames that contain things like \..\ (this is known as "directory traversal attack").
And on the client side:
function testFunc(selector, filename) {
$(selector).attr("src", "/tester/" + encodeURIComponent(filename) );
}
The use of encodeURIComponent() is good style and prevents problems with filenames that contain special characters. The browser will request the image as soon as its src attribute changes, there is no need to do anything via Ajax here.
Preventing a directory traversal attack with send_file() alone is a bit more involved:
filepath = os.path.realpath(os.path.join(IMAGE_DIR, filename))
if os.path.commonprefix([filepath, IMAGE_DIR]) != IMAGE_DIR:
abort(404)
return send_file(filepath)
File paths on Windows are case-insensitive, so IMAGE_DIR should contain the actual case of the path, otherwise this test will fail.
Solved:
function testFunc(args) {
selector = args.data[0];
filename = args.data[1];
var obj = JSON.stringify({"data" : filename});
console.log(obj);
$.ajax({
url: '/tester2/', //server url
type: 'GET', //passing data as post method
data: obj,
async: false,
success: function(data) {
$(selector).attr("src", "/tester2/");
},
});
};
I was assigning the raw data to the src attribute, but I needed to assign the URL of the GET request to the src attribute.
Related
I'm a beginner.
What I used was flask and pymongo.
If you press the button, it's "Like". It should be +1, but there is a key error at the bottom.
My python route code:
#app.route('/api/like', methods=['POST'])
def like_movie():
title_receive = request.form['title_give']
movie = db.toytoy.find_one({'title': title_receive})
current_like = movie['like']
new_like = current_like + 1
db.toytoy.update_one({'title': title_receive}, {'$set': {'like': new_like}})
return jsonify({'msg': 'like!'})
This is how I POST from JS
function like_movie(title) {
$.ajax({
type: 'POST',
url: '/api/like',
data: {title_give: title},
success: function (response) {
console.log(response)
alert(response['msg']);
window.location.reload();
}
});
}
I get an exception as below:
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'title_give'
What I want is if it's 'like_btn'. If you press the button, it becomes +1.
The base problem in what you did is not respecting Content-type. From front JS, you are making a POST with JSON object. Which makes the request to have a content type of application/json.
In backend code, you use request.form which expects the request to be in the form encoded types (like application/x-www-form-urlencoded, multipart/form-data) etc.
So, you need to read the JSON content in backend, instead of reading from a form which is not available. Like below:
ui_req = request.get_json()
title_receive = ui_req['title_give']
And then parse other structures accordingly.
I have one button in my react code and when I click it I should be able to download a file. I am using Python for backend(Not any framework). For react part I think this link explains what should be done. On button click, I should do an API call and on its return, I can render this IFrame component. Also, one other answer recommends responseType: 'blob' in axios call. My question is what should the backend do if we want to send a file over.Let's assume it just creates a file and returns it. I am actually using one third-party product which has its own API interface but an example with requests library would do.
def function_called_From_endpoint():
with open(path) as f:
return {'data': f }
Is something like this right?
So, I made it work this way:
def function_called_From_endpoint():
with open(file_path) as f:
data = f.read()
return {"data": data }
and on the front-end:
axios({
url: url, //your url
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.txt'); //or any other extension
document.body.appendChild(link);
link.click();
});
As suggested by https://stackoverflow.com/a/53230807/5573241. It worked well.
I am reviewing this repository https://github.com/ibrahim4529/flask-chatbot to get an inspiration and see how a model can be deployed in a chat UI. I am able to do this in Flask but ran across a quirky situation that I am not sure how to resolve. The UI accepts the first initial message that I type, but when I try returning the response, I get an 'undefined' appended to every line that is supposed to be the bot's response. On CMD though, my function is returning response. I've provided screenshots below:
Here is my routing:
#app.route('/')
def hello():
return render_template('index.html')
#app.route('/ask', methods={'POST', 'GET'})
def ask():
if request.method == 'POST':
message = (request.form['messageText'])
bresponse = response(message)
return render_template('Index.html', bresponse=bresponse)
'response' is a function that spits out the response of the model (this is the 'Rrraawwwwg!' response from the input).
Below is the js that I reviewed from the link that I am using:
$('#chatbot-form').submit(function(e) {
e.preventDefault();
var message = $('#messageText').val();
$(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div style = "text-align:right; color : #2EFE2E" class="media-body">' + message + '<hr/></div></div></div></li>');
$.ajax({
type: "POST",
url: "/ask",
data: $(this).serialize(),
success: function(response) {
//console.log(response);
$('#messageText').val('');
var answers = response.answers;
const chatPanel = document.getElementById("chatPanel");
$(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div style = "color : white" class="media-body">' + answers + '<hr/></div></div></div></li>');
$(".fixed-panel").stop().animate({ scrollTop: $(".fixed-panel")[0].scrollHeight}, 1000);
I am not sure what I am missing. I am seeing the response in the cli, but seeing an undefined in the UI.
Thanks in advance!
I finally was able to make this work. I've updated ajax to below:
var answers = response;
$('#messageText').val();
I was also printing the response function, instead of returning it; reason I am seeing the response in the console and not in the view. This was the main culprit.
Been at this for hours, giving up and posting in the hopes someone can help me out. Maybe this is a terribly stupid idea but I:
Have an html page that I modify using some jQuery controls (adding classes to a large list of items individually on click, filling in textareas, changing page title, etc..
On click of a save button want to do something like :
$('#save').click(function() {
myhtml = $('html').html();
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/parse_data",
data: myhtml
});
});
Then on the Python/Flask side:
#app.route('/parse_me', methods=['GET', 'POST'])
def parse_me():
if request.method == "POST":
#determine new filename based on #header id
#save new file with request.form data? request.something data??
#using the new filename
I read over the flask docs, and tried many many variations. I'm thinking my problem primarily lies in how I'm sending & then unpacking the data. The closest I got was using:
data: JSON.stringfy(myhtml)
and then on the python side I could "see" that data by doing
print request.values
inside the parse_me() method. Any help would be appreciated. It seemed like the "simplest" solution to what I want to accomplish: I modify the dom with jQuery then ship off my changes to flask to package them into a new file on the server.
Solved!
changed :
$('#save').click(function() {
myhtml = $('html').html();
$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/parse_data",
data: {html:myhtml} // made into a hash for retrieval
});
});
on the python side :
#app.route('/parse_data', methods=['GET', 'POST'])
def parse_data():
# updated: get value for key "html", encode correctly
data = request.form.get("html").encode("utf-8")
# do whatever with the data
return "Data retrieved"
Very easy.. loving Flask!
I'm using an AJAX call to get data from the server:
$.ajax({
type: 'POST',
url: '/simple/gd/',
dataType: 'json',
data: {t : "PL"},
success: function(data) {
var newd = data['t'];
alert('Load was performed: ' + newd);
}
});
On the server, urls.py is:
(r'^simple/gd/(?P<data>.*)$', 'simple.views.getData'),
The url that's getting to the server is http:/localhost/simple/gd/?t=PL
But for some reason, I can't make getData(request, data) to be called with "?t=PL" or with "t=PL" as 'data' parameter. 'data' is always empty.
What am I doing wrong?
If you use type: 'POST' then the data doesn't get appended to the URL as a query string.
Instead, it is included in the request object's POST dictionary.
So in order to pass something back that fires your alert you need to render a string that can be interpreted as json data something along the lines of:
(r'^simple/gd/$', 'simple.views.getData'),
def getData(request):
posted_t = request.POST['t']
# Do some stuff with posted_t
server_side_var = "Yay"
return HttpResponse(u"{t:%s}" % server_side_var)
That's because t=PL is not part of the path, it's the query string (the path, roughly speaking, is the bit before the ?, the query string is the bit after the ?).
Personally, I'd recommend changing your urls.py as follows:
(r'^simple/gd/$', 'simple.views.getData'),
Then, adjust your view function from something like:
def getData(request, data):
print data
to something like:
def getData(request):
print request.GET.get('t', None)