I want to send a JavaScript variable with a image that a user will upload to my Flask file where processing will be done. So I am using Formdata and a AJAX call for the same. But after the data and image is received in flask and processing is done, I am unable to render a HTML page in flask which will display the processed image .
Java Script Code :
formdata = new FormData();
jQuery("#image_to_upload").on("change", function() { // On Change Of image upload
var file = this.files[0];
if (formdata) {
formdata.append("file", file);
formdata.append("array", filtersActive);
jQuery.ajax({
url: "/object-detect-uploader",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success:function(){}
});
}
});
Flask Code :
#app.route("/object-detect-uploader", methods = ['GET', 'POST'])
def upload_object_detection():
detect_objs = request.values['array'].split(",")
d_array= [0 for i in range(6) ]
for i in detect_objs:
d_array[int(i)] = 1
for upload in request.files.getlist("file"):
filename = upload.filename
# This is to verify files are supported
ext = os.path.splitext(filename)[1]
if (ext == ".jpg") or (ext == ".png"): #File extention check
print("File supported moving on...")
ans=(object_detection_module.object_detection(upload,d_array))
else:
render_template("Error.html", message="Files uploaded are not supported...")
print("Rendering")
return render_template("index.html", result = ans)
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<br>
<br>
<h1><center>Output</h1></center>
<br>
<img src="data:image/png;base64, {{result[0]}}" >
<br>
<br>
<h2> No of objects = {{ result[1] }}</h2>
</body>
</html>
An Ajax call is an asynchronous request initiated by the browser that does not reload the page when it receives the server response.
IMO, since you want to render the template, you should not use AJAX, just use a normal <form> element or create a form programmatically, fill the data, then submit with jQuery('selector').submit().
Related
I have almost the same problem that in thread "Adobe PDF Embed API can not change the pdf" and "How to use a variable in Adobe's pdf embed API as URL-value?". which both were addressed by Mr Raymond Camden. The only difference is that I am trying to pass an url to location:url from Flask. Here's the code:
if(window.AdobeDC) displayPDF(urldata);
else document.addEventListener("adobe_dc_view_sdk.ready",
() => displayPDF(urldata));
function displayPDF(urldata) {
document.writeln(urldata[0]);
document.writeln(urldata[1]);
var myURL = urldata[0];
var myFileName = urldata[1];
adobeDCView.previewFile({
content: {
location: {
url: myURL,
},
},
metaData: {
fileName: myFileName
}
}, viewerConfig);
}
Note that I am using Mr Camden trick for dealing with
well-seasoned chicken and nice fresh eggs
.
I can get my 2 parameters going to the html file and to the js file. They are both writelined on the page from the displayPDF(urldata) function. Unfortunately they don't make it to content:location:url and metadata:filename. If I do hardcode these two parameters with existing PDF url and filename I get the result I want to obtain.
What am I doing wrong?
Thanks to anybody who could give me a clue.
All the best,
Pierre-Emmanuel FEGA
zepef#hotmail.com
I've found an answer to my own question. I have posted it on Adobe Community forum as well because "Passing value from external function to document function" because both responses from Shubhanshu Dixit and Raymond Camden have been of great help to me.
My goal was to open a PDF file coming from Azure Blob Storage to use it in an Azure Web App. The app is in Flask. Here's how I've done it and it works great on Azure as well as locally:
FLASK ROUTE
#app.route("/document", methods=['GET', 'POST'])
def document():
# Microsoft blob storage SAS token creation for accessing PDF file in blob storage
blob = get_blob_sas(BLOB_NAME_PATH, STORAGE_ACCOUNT_KEY, BLOB_CONTAINER_NAME, document_to_retrieve)
blob_url = 'https://'+BLOB_NAME_PATH+'.blob.core.windows.net/'+BLOB_CONTAINER_NAME+'/'+document_to_retrieve+'?'+blob
# URL and Filename parameters to send to Adobe Embed API
urldata = [blob_url, document_to_retrieve]
return render_template('view.html', title='SYSTRA Semantic Selected Document', urldata=urldata)
HTML PAGE
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1"/>
<script type="text/javascript" src="{{ url_for('static', filename='view.js') }}"></script>
<script type="text/javascript">
varPDF = previewFile({{urldata|tojson}})
</script>
</head>
<body style="margin: 0px">
<div id="adobe-dc-view"></div>
<script type="text/javascript" src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
</body>
</html>
JAVASCRIPT FUNCTIONS
function previewFile(urldata) {
var myURL = urldata[0];
var myFileName = urldata[1];
if(window.AdobeDC) displayPDF(myURL, myFileName);
else document.addEventListener("adobe_dc_view_sdk.ready",
() => displayPDF(myURL, myFileName));
}
function displayPDF(myURL, myFileName) {
document.write('displayPDF');
const viewerConfig = {
embedMode: "FULL_WINDOW",
defaultViewMode: "FIT_PAGE",
showLeftHandPanel: true,
showAnnotationTools: true,
showDownloadPDF: true,
showPrintPDF: true,
showPageControls: true,
showDisabledSaveButton: true,
downloadWithCredentials: true
};
var adobeDCView = new AdobeDC.View({
clientId: '<CLIENT_ID_KEY_HERE',
divId: "adobe-dc-view"
});
adobeDCView.previewFile({
content: {
location: {
url: myURL,
},
},
metaData: {
fileName: myFileName
}
}, viewerConfig);
}
I hope this helps.
All the best,
Pierre-Emmanuel
I am trying to track the number of times a button or a dropdown is clicked in my flask app and send it back to python backend so i can input into database. I keep getting null for my value i cant seem to figure it out.
new.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form method = "POST">
<button type="button" id = "numberclicks" name = "numberclicks" onClick="onClick()">Click me</button>
<p>Clicks: <a id="clicks" name ="clicks" placeholder = 0 >{{clicks|safe}}</a></p>
<button type="submit">Login</button>
</form>
</div>
<script>
var clicks = 0;
function onClick() {
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
console.log(clicks)
}
</script>
</body>
</html>
app.py
from flask import Flask,render_template,request
import json
app = Flask(__name__)
# turn this into calss and import to record who is logged in to the session aka. user then take log data and make relationship to tables
# HOW MANY TIMES USER VISITED THE VISIT PAGE!!!
#app.route('/', methods=['POST', 'GET'])
def signUpUser():
if request.method == "POST":
click = request.args.get('clicks',type = int)
return json.dumps({'status':'OK','click':click})
return render_template("new.html")
if __name__ == "__main__":
app.run(debug=True)
function onClick() {
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
console.log(clicks);
fetch("/", {
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify({clicks}),
});
}
You could use the XMLHttpRequest object to send the clicks count asychronously to the flask backend.
const xhr = new XMLHttpRequest();
xhr.open("POST", "/", true);
xhr.onload = () => {
if (xhr.status === 200) {
...do whatever you want...
}
}
const data = new FormData();
data.append("clicks", clicks);
xhr.send(data);
I want to open the response that I get from my PHP server in the In App Browser in a new window.
I am creating an app using Ionic and using PHP as a back end. I have full control of the php server.
I am making the ajax call like so:
$(document).ready( function() {
$("#paybutton").click(function() {
var params = "projectpaymentoption=1197&id=",
usernamepay = window.localStorage.getItem("username"),
paymenturl = params + usernamepay;
$.ajax({
type: 'POST',
url: 'http://www.blabla.com/encode.php',
data: $.param({"paymenturl": paymenturl}),
success: function(output) {
window.open('output','_blank','location=no','closebuttoncaption=Zurück');
console.log(result);
}
});
});
});
Now I want to open the output in a new inappbrowser windows.
The output i am throwing out is as follows
<?php
ob_start();
include_once('includes/headers.php');
require_once('includes/connection.php');
require_once('includes/functions.php');
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
</head>
<?php
include($filePath);
?>
It is a dynamically generated php page. An not an url.
How can I show this page in the inappbrowser
I'm calling the uberGallery (www.uberGallery.net) from the index.php like so:
<?php
include_once 'resources/UberGallery.php';
include_once 'resources/uberCall.php';
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
...
<link rel="stylesheet" type="text/css" href="resources/themes/uber-naked/style.css" />
<link rel="stylesheet" type="text/css" href="resources/colorbox/5/colorbox.css" />
<script src="//code.jquery.com/jquery.js"></script>
<script type="text/javascript" src="resources/colorbox/jquery.colorbox.js"></script>
</head>
<body>
<div class = "row">
<div class = "col col-lg-12">
<h2 id = "locName"></h2>
</div>
</div>
<div id="gallery">
<?php
$path = "london";
getGallery($path);
$path = "paris";
getGallery($path);
$path = "rome";
getGallery($path);
?>
</div>
<script type="text/javascript" src='js/UX.js'></script>
</body>
</html>
The uberCall.php is like that:
<?php
include_once ('UberGallery.php');
function getGallery($pathToImage){
UberGallery::init() -> createGallery('locations/'.$pathToImage.'/gallery');
}
if(isset( $_POST['image-path'] )) {
$path = $_POST['image-path'];
UberGallery::init() -> createGallery('locations/'.$path.'/gallery');
}
?>
So far this is working like expected.
Now I would like to load the galleries from a dropdown menue and just show the selected gallery. The dropdown selection is done in a jQuery script:
$(document).ready(function() {
$("a[rel='colorbox']").colorbox({
maxWidth : "90%",
maxHeight : "90%",
opacity : ".5"
});
$(".dropdown-toggle").dropdown();
$('#demolist li a').click(function(e) {
$('#locationSelector').val($(this).text());
var $this = $(this);
var selLocID = $this.attr("value");
e.preventDefault();
var dataString = {
'location_id' : selLocID
};
$.ajax({
type : 'POST',
dataType : 'json',
url : 'includes/locationAPI.php',
data : dataString,
success : function(data) {
$('#locData').html('');
// erase content if any
$('#locName').html(data['name']);
// from MySQL
// set location headline
$.ajax({
type : "POST",
data : {
'image-path' : data['pfad'] // from MySQL
},
url : 'resources/uberCall.php',
dataType : "html",
async : false,
success : function(data) {
result = data;
alert(result);
$('#gallery').html(result);
}
});
}
});
});
});
When going this route the ubergallery doesn't find any folders, though I'm adressing the exact same uber.php as I would from the index.php.
I have looked into the ubergallery.php with xdebug and it would be called with exactly the same parameters.
Also I tried to call createGallery() without init:: and also explicitly create a new instance of the UberGallery class before calling createGallery.
All with no luck.
What am I doing wrong here?
In your resources/userCall.php script you are not actually calling the gallery function in order to render it. This appears to be the target of the second AJAX request. The script is merely defining the function.
EDIT: You've since updated the code in your question to include the call.
Assuming image-path is the parameter you want to supply as $pathToImage you will need to have a script that calls the function getGallery passing the value from $_POST['image-path'].
For example:
<?php
require_once('resources/uberCall.php');
getGallery($_POST['image-path']);
NOTE: Without any filtering sanitisation, bear in mind this could be potentially dangerous as I could pass an image-path parameter that picks a naughty directory.
Then use that script as the target of your second AJAX call.
P.S. Remove the async: false in the second AJAX call, it stops any other interactivity on your page whilst the request is in flight.
Bear in mind that with your parameter checking in the resources/userCall.php the original request is down a directory from the second request. This means the working directory for the second request will be different, the path will resolve to "resources/locations/$path/gallery" and not "locations/$path/gallery".
You are best off creating a second script for the AJAX action in the same directory as the original and requiring in the resource/userCall.php as per the first script. Or using a configurable absolute directory path to resolve the gallery location:
<?php
require_once('UberGallery.php');
require_once('config.php');
function getGallery($path) {
UberGallery::init() -> createGallery("{$config['gallery_base_path']}/$path/gallery");
}
With $config['gallery_base_path'] being something like /absolute/path/to/my/application/locations.
Additional confusion can be caused by not knowing whether file operations will use the include path, some file options can be told to use the include path which may include the current file path and current script directory, but if not it will only try to find the file from the current working directory. Whereas include and require all use the include path and current script directory as potential points to find a script.
P.S.P.S Use getcwd to find out what the current working directory is at any point in your scripts.
my angular js code is failing to upload an image with the imgur API.
angular js http post method
angular js http post method
HTML:
<!doctype html>
<html ng-app="stalkcalibrator">
<head>
<title>Corn Stalk Calibrator</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="style/style.css"/>
<script src="angular.js"></script>
<script src="controllers.js"></script>
</head>
<body ng-controller="adminController">
<h1 id="title">Calibrator - Admin Upload</h1>
<!-- back to admin home -->
<div id="back">Admin Home</div>
<!-- form used to upload one or more images -->
<form>
<!-- button allows user to browse local directory for image -->
<!-- ng-model saves image var in array -->
Upload image <input type="file" ng-model="img" accept="image/*" id="file" />
<!-- executes js upload function with uploaded images -->
<button><a ng-click="upload()">Submit</a></button>
<p ng-model="num">{{num}}</p>
</form>
</body>
</html>
Here's my JS:
var stalkcalibrator = angular.module('stalkcalibrator', []);
stalkcalibrator.controller('adminController', function($scope){
//array of data for each stalk. PULL FROM JSON FILE!
$scope.stalks = [{id:1, name:2, thumbnail:3, note:4}, {id:9, name:10, thumbnail:11, note:12}, {id:5, name:6, thumbnail:7, note:8}];
//array of image uploads
$scope.img;
$scope.num = 1;
function getStalks($scope){
}
$scope.upload = function() {
$http({
headers: {'Authorization': 'Client-ID 010fe699c18e3c9'},
url: 'https://api.imgur.com/3/',
type: 'POST',
data: {'image': $scope.img}
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.num = 2;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.num = 3;
});
//adds image data to JSON file
//_TODO_
};
});
Thanks!
EDIT: neither errorCallback nor successCallback is being called back.
I would change your code like this:
angular.module('stalkcalibrator', []) //best practise is not to declare a variable to contain this
.controller('adminController',['$scope','$log','$http', function($scope,$log,$http){ // safe dependency injection
var self = this; //self will contain the data from the controller. I dislike to put all into the scope.
//array of data for each stalk. PULL FROM JSON FILE!
self.stalks = [{id:1, name:2, thumbnail:3, note:4}, {id:9, name:10, thumbnail:11, note:12}, {id:5, name:6, thumbnail:7, note:8}];
//array of image uploads
self.img;
self.num = 1;
self.getStalks = function($scope){};
self.upload = function() {
$http({
headers: {'Authorization': 'Client-ID 010fe699c18e3c9'},
url: 'https://api.imgur.com/3/',
type: 'POST',
data: {'image': self.img}
}).then(function successCallback(response) {
self.num = 2;
$log.log('called and successful', response);
}, function errorCallback(err) {
self.num = 3;
$log.log('called but error', err);
});
};
}]);
Then the html:
<body ng-controller="adminController as ac">
<h1 id="title">Calibrator - Admin Upload</h1>
<!-- back to admin home -->
<div id="back">Admin Home</div>
<!-- form used to upload one or more images -->
<form>
Upload image <input type="file" ng-model="ac.img" accept="image/*" id="file" />
<!-- executes js upload function with uploaded images -->
<button ng-click="ac.upload()">Submit</button>
<p ng-bind="ac.num"></p>
</form>
</body>
Try this, I think the problem might have been in
<button><a ng-click="upload()">Submit</a></button>
You were clicking on the button and not on the text (that was the actual anchor that was able to call the upload function).
With this we should at least be able to see something in console
Resolved. It turns out that self.img was the wrong file type for the Imgur API. Had to convert to base64 and make edits suggested by #Gianmarco