I'm trying to send a file path to my Ajax script which reads file contents and displays it on the page
#app.route('/main', methods=['GET'])
def main():
filename = '/static/js/'+current_user.username+'log.txt'
return render_template('main.html',name=current_user.username,data=filename)
js script
var checkInterval = 1; //seconds
var fileServer = '{{ data }}';
var lastData;
function checkFile() {
$.get(fileServer, function (data) {
if (lastData !== data) {
$( "#target" ).val( data );
$( "#target" ).animate({
scrollTop: $( "#target" )[0].scrollHeight - $( "#target" ).height()
}, 'slow');
lastData = data;
}
});
}
$(document).ready(function () {
setInterval(checkFile, 1000 * checkInterval);
});
I tried different ways to do this, changed fileServer to 'data.filename'/{{ data| json }} etc but got no luck.
How can I do this?
If you pass the entire url generated with url_for as a parameter it should work.
#app.route('/main', methods=['GET'])
def main():
filename = url_for('static', filename=f'js/{current_user.username}log.txt')
return render_template('main.html', name=current_user.username, data=filename)
As a supplement, I also specify that the request should not be stored in the cache.
const checkInterval = 1;
const fileServer = "{{ data }}";
let lastData;
function checkFile() {
$.get({ url: fileServer, cache: false }, function(data) {
if (lastData !== data) {
$("#target").val(data);
$("#target").animate({
scrollTop: $("#target")[0].scrollHeight - $("#target").height()
}, "slow");
lastData = data;
}
});
}
$(document).ready(function() {
setInterval(checkFile, 1000 * checkInterval);
});
I used jquery version 3 for testing.
Related
The issue.
My code below works (uploads the file) when I run it on my phone using expo r -c
Does NOT work (no files in request object) when i run npm run web or expo r -c followed by w
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, Button } from "react-native";
import * as DocumentPicker from "expo-document-picker";
export default function App() {
const _pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({
type: "*/*",
copyToCacheDirectory: true,
});
alert(result.uri);
console.log(result);
const imageUri = result.uri.replace("file:/data", "file:///data");
const data = new FormData();
data.append("file", {
name: result.name,
type: result.mimeType,
uri: imageUri,
});
const options = {
method: "POST",
body: data,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data",
},
};
const base_domain =
"http://192.168.1.83:5000" + "/api/v1/manager/file-upload";
fetch(base_domain, options).catch((error) => console.log(error));
};
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
<Button title="Select Document" onPress={_pickDocument} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Backend
#manager.route("/file-upload", methods=["POST"])
#csrf.exempt
def upload_file():
# check if the post request has the file part
print("Request Files", request.files)
return jsonify({"status": "ok"})
For the web case request.files gives me an empty dict.
I am calling ajax request from frontend to export data in excel sheet.
js
function exportData(){
create_spinner("Please wait while we export data.");
var agent = $("#agent").val()
var dateRange = $("#dateRangeValue").val()
var queue = $("#queue").val()
var direction = $("#direction").val()
var department = $("#department").val()
var serviceLevel = $("#sl").val()
$.ajax({
type: 'POST',
url: "/call-record-api/export-data/",
data: {
"agent": agent,
"dateRange": dateRange,
"queue": queue,
"direction": direction,
"department": department,
"serviceLevel": serviceLevel,
},
success: function(resultData) {
console.log("success");
hide_spinner();
},
error: function (err) {
console.log("AJAX error in request: " + JSON.stringify(err, null, 2));
create_spinner("Couldn't export data. Please try again");
setTimeout(function(){ hide_spinner()}, 1000);
}
});
}
I have gone through documentation and implemented the same.
urls.py
url(r'^call-record-api/export-data/$', ExportCallRecordView.as_view({"post":"list"})),
views.py
class ExportCallRecordView(XLSXFileMixin, ReadOnlyModelViewSet):
def get_queryset(self):
calls = export_customized_calls(self.request)
print(calls.count())
return calls
serializer_class = CallRecordSerializer
renderer_classes = [XLSXRenderer]
filename = 'call_record_export.xlsx'
But i cannot see the file getting downloaded. However i can see success in browser console and 235 as call count in server console.
You can't download files directly with ajax. You have to use tricks like this (taken from a github repo):
// jQuery ajax
$.ajax({
type: "POST",
url: url,
data: params,
success: function(response, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
Or if you don't mind converting your POST request in to GET request:
window.location = `/<download_url>/?param1=${encodeURIComponent(param1)}`
I am unable to make post request via react js to python-flask server.
I am using axios. This request works on postman, but I can't seem to figure out why I can make post request from my react app.
Please see flask code:
#app.route('/match_home_types', methods=['GET', 'POST'])
def match_home_types():
area = request.form['area']
response = jsonify({
'home_types': util.match_area_with_types(area)
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
My react-redux action code:
export const matchHouseTypes = (area) => (dispatch) => {
axios
.post("http://127.0.0.1:5000/match_home_types", area)
.then((res) => {
dispatch({
type: MATCH_TYPES,
payload: res.data.home_types,
});
})
.catch((error) => {
console.log(error.response);
});
};
my react class component:
get_house_types = () => {
const { selectedOption } = this.state;
if (selectedOption == "Find a location") {
alert("Please select a valid location");
}
var area = {
area: selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase()),
};
console.log("area:", area);
this.props.matchHouseTypes(area);
};
See below error response from axios:
data: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">↵<title>400 Bad Request</title>↵<h1>Bad Request</h1>↵<p>The browser (or proxy) sent a request that this server could not understand.</p>↵"
status: 400
statusText: "Bad Request"
Please assist
The issue was that I was not sending the API parameters the right way. Since I am sending via form data I changed my code from:
var area = {
area: selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase()),
};
to:
const formData = new FormData();
formData.append(
"area",
selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase())
);
complete function:
get_house_types = (e) => {
e.preventDefault();
const { selectedOption } = this.state;
if (selectedOption == "Find a location") {
alert("Please select a valid location");
} else {
const formData = new FormData();
formData.append(
"area",
selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase())
);
this.props.matchHouseTypes(formData);
}
};
I am working on AWS Sagemaker and my goal is to follow this tutorial from Pytorch's official documentation.
The original predict function from the tutorial above is the following:
#app.route('/predict', methods=['POST'])
def predict():
if request.method == 'POST':
file = request.files['file']
img_bytes = file.read()
class_id, class_name = get_prediction(image_bytes=img_bytes)
return jsonify({'class_id': class_id, 'class_name': class_name})
I was getting this error, so I added 'GET' as a method as mentioned in here. I also simplified my example to its minimal expression:
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/predict', methods=['GET','POST'])
def predict():
if request.method == 'POST':
return jsonify({'class_name': 'cat'})
return 'OK'
if __name__ == '__main__':
app.run()
I perform requests with the following code:
import requests
resp = requests.post("https://catdogclassifier.notebook.eu-west-1.sagemaker.aws/proxy/5000/predict",
files={"file": open('/home/ec2-user/SageMaker/cat.jpg', 'rb')})
resp is <Response [200]> but resp.json() returns JSONDecodeError: Expecting value: line 1 column 1 (char 0) Finally, resp.url points me to a page saying 'OK'.
Moreover, this is the output of resp.content
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#loadingImage {
margin: 10em auto;
width: 234px;
height: 238px;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,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);
-webkit-animation:spin 4s linear infinite;
-moz-animation:spin 4s linear infinite;
animation:spin 4s linear infinite;
}
#-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
#-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
#keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
</style>
</head>
<body>
<div id="loadingImage"></div>
<script type="text/javascript">
var RegionFinder = (function()
{
function RegionFinder( location ) {
this.location = location;
}
RegionFinder.prototype = {
getURLWithRegion: function() {
var isDynamicDefaultRegion = ifPathContains(this.location.pathname, "region/dynamic-default-region");
var queryArgs = removeURLParameter(this.location.search, "region");
var hashArgs = this.location.href.split("#")[1] || "";
if (hashArgs) {
hashArgs = "#" + hashArgs;
}
var region = this._getCurrentRegion();
var newArgs = "region=" + region;
if (_shouldAuth()) {
newArgs = "needs_auth=true";
region = "nil";
}
if (queryArgs &&
queryArgs != "?") {
queryArgs += "&" + newArgs;
} else {
queryArgs = "?" + newArgs;
}
if (!region) {
var contactUs = "https://portal.aws.amazon.com/gp/aws/html-forms-controller/contactus/aws-report-issue1";
alert("How embarrassing! There is something wrong with this URL, please contact AWS at " + contactUs);
}
var pathname = isDynamicDefaultRegion ? "/console/home" : this.location.pathname;
return this.location.protocol + "//" + _getRedirectHostFromAttributes() +
pathname + queryArgs + hashArgs;
},
_getCurrentRegion: function() {
return _getRegionFromHash( this.location ) ||
_getRegionFromAttributes();
}
};
function ifPathContains(url, parameter) {
return (url.indexOf(parameter) != -1);
}
function removeURLParameter(url, parameter) {
var urlparts= url.split('?');
if (urlparts.length>=2) {
var prefix= encodeURIComponent(parameter);
var pars= urlparts[1].split(/[&;]/g);
//reverse iteration as may be destructive
for (var i= pars.length; i-- > 0;) {
if (pars[i].lastIndexOf(prefix, 0) !== -1) {
pars.splice(i, 1);
}
}
url= urlparts[0]+'?'+pars.join('&');
return url;
} else {
return url;
}
}
function _getRegionFromAttributes() {
return "eu-west-1";
};
function _shouldAuth() {
return "";
};
function _getRedirectHostFromAttributes() {
return "eu-west-1.console.aws.amazon.com";
}
function _getRegionFromHash( location ) {
var hashArgs = "#" + (location.href.split("#")[1] || "");
var hashRegionArg = "";
var match = hashArgs.match("region=([a-zA-Z0-9-]+)");
if (match && match.length > 1 && match[1]) {
hashRegionArg = match[1];
}
return hashRegionArg;
}
return RegionFinder;
})();
var regionFinder = new RegionFinder( window.location );
window.location.href = regionFinder.getURLWithRegion();
</script>
</body>
</html>
What am I missing?
Looks like the content of your resp is HTML as opposed to JSON; this is likely a consequence of how the Jupyter server proxy endpoint you're attempting to POST to (https://catdogclassifier.notebook.eu-west-1.sagemaker.aws/proxy/5000/predict) is configured.
It looks like you're using a SageMaker notebook instance, so you might not have much control over this configuration. A workaround could be to instead deploy your Flask server as a SageMaker endpoint running outside JupyterLab, instead of directly on a notebook instance.
If you want to prototype using only a notebook instance, you can alternately just bypass the proxy entirely and simply call your Flask route relative to localhost from another notebook tab while the Flask server runs in your main notebook tab:
import requests
resp = requests.post("https://localhost:5000/predict",
files={"file": open('/home/ec2-user/SageMaker/cat.jpg', 'rb')})
This script
<script type="text/javascript">
$(function() {
$('.send').live('click', 'button', function()
{
var user1 = $(this).val();
var user2=$(this).prev().val();
var text=$(this).prev().prev().val();
var my_data = {
user1: user1, text:text, user2:user2,
};
console.log(my_data)
$.ajax({
url: "/updatechat",
data: my_data,
type: 'POST',
success: function(response) {
console.log(response)
},
error: function(error) {
console.log(error);
}
});
});
});
is raising an error with the correspondent route /updatechat
#app.route('/updatechat', methods=['GET','POST'])
def updatechat():
user1 = request.form['user1']
user2 = request.form['user2']
text = request.form['text']
return [user1,user2,text] #not the actual code
but will NOT raise the same error if, in the previous piece of code, i replace with this
user1='bbb'
user2='whatever'
text='idk'
this "var = request.form['var']" form works on several different routes on my code
Solved
The proper form was user1 = request.values.get("user1")
source: https://stackoverflow.com/a/20341272