Upload an Image and Display it back as a response using Flask - python

I'm a beginner in front end development, and have to do a small web app in Flask for a project.
I have written a Flask app that lets you upload an image using HTML Forms and then displays the image back to the user when you hit Upload. I need to modify this such that the image does not get saved to a folder in the project directory everytime a user uploads it. Basically, the app should send the uploaded image back in the body of the response.
Here is my code so far:
UploadTest.py
import os
from uuid import uuid4
from flask import Flask, request, render_template, send_from_directory
app = Flask(__name__)
# app = Flask(__name__, static_folder="images")
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
#app.route("/")
def index():
return render_template("upload.html")
#app.route("/upload", methods=["POST"])
def upload():
target = os.path.join(APP_ROOT, 'images/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
else:
print("Couldn't create upload directory: {}".format(target))
print(request.files.getlist("file"))
for upload in request.files.getlist("file"):
print(upload)
print("{} is the file name".format(upload.filename))
filename = upload.filename
destination = "/".join([target, filename])
print ("Accept incoming file:", filename)
print ("Save it to:", destination)
upload.save(destination)
return render_template("complete.html", image_name=filename)
#app.route('/upload/<filename>')
def send_image(filename):
return send_from_directory("images", filename)
if __name__ == "__main__":
app.run(port=8080, debug=True)
upload.html - creates an upload form
<!DOCTYPE html>
<html>
<head>
<title>Upload</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>
<form id="upload-form" action="{{ url_for('upload') }}" method="POST" enctype="multipart/form-data">
<strong>Files:</strong><br>
<input id="file-picker" type="file" name="file" accept="image/*" multiple>
<div id="msg"></div>
<input type="submit" value="Upload!" id="upload-button">
</form>
</body>
<script>
$("#file-picker").change(function(){
var input = document.getElementById('file-picker');
for (var i=0; i<input.files.length; i++)
{
var ext= input.files[i].name.substring(input.files[i].name.lastIndexOf('.')+1).toLowerCase()
if ((ext == 'jpg') || (ext == 'png'))
{
$("#msg").text("Files are supported")
}
else
{
$("#msg").text("Files are NOT supported")
document.getElementById("file-picker").value ="";
}
}
} );
</script>
</html>
complete.html - displays the image from the folder in which it has been saved after a user hits "upload"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Uploaded
<img src=" {{url_for('send_image', filename=image_name)}}">
</body>
</html>
I have tried researching quite a bit but was unable to find anything other than deleting the folder after it has been displayed (which I didn't think is the right way of solving the question at hand). I'd really appreciate any help in this matter, and if there is a better solution than what my code currently does, I'd love to learn more!
Thank you! :)

Please check below code can help you.Copy the below code in upload.html in templates folder.
<!DOCTYPE html>
<html>
<head>
<link class="jsbin" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.0/jquery-ui.min.js"></script>
<meta charset=utf-8 />
<script src="{{ url_for('static', filename='upload.js') }}"></script>
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
</head>
<body>
<form action = "http://127.0.0.1:5000/uploader" method = "POST"
enctype = "multipart/form-data">
<input type='file' name = 'file' onchange="readURL(this);" />
<img id="blah" src="#" alt="your image" />
<input type = "submit"/>
</form>
</body>
</html>
Copy the below code in upload.js file in static folder
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah')
.attr('src', e.target.result)
.width(150)
.height(200);
};
reader.readAsDataURL(input.files[0]);
}
}
Now copy the below code in a python file
from flask import Flask, render_template, request
from werkzeug import secure_filename
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'D:/Projects/flask/image_upload/images/'
#app.route('/')
def upload_f():
return render_template('upload.html')
#app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename)))
return 'file uploaded successfully'
# if __name__ == '__main__':
app.run(debug = True)
Above piece of code will help you to browse and display the image on html page and as well save the image on your disk at desired location.

If you want to send back image to client there's 2 approach,
You can send image to client as an file url
You need to convert an image as blob or base64 image and show image

Related

Python Flask not saving to folder

i am trying to create a Python/Flask app where the user saves an image to a local folder . It creates the folder , i get the "has been uploaded" success page but the image was not saved in the folder
this is my .py code
import os
from flask import Flask, render_template, request
app = Flask(__name__)
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
#app.route("/")
def index():
return render_template("upload.html")
#app.route("/upload", methods=['GET','POST'])
def upload():
target = os.path.join(APP_ROOT, 'images/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("file"):
print(file)
filename = file.filename
destination = "/".join([target, filename])
print(destination)
file.save(destination)
return render_template("complete.html")
if __name__ == "__main__":
app.run(port=4555, debug=True)
this is my .html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Upload here</h1>
<form id="upload-form" action="{{url_for('upload')}}" methods="POST" enctype="multipart/form-data">
<input type="file" name="file" accept="image/*" multiple>
<input type="submit" value="send">
</form>
</body>
</html>
You have a typo in your html markup where you define the form. It should say:
<form id="upload-form" action="{{url_for('upload')}}" method="POST" enctype="multipart/form-data">
As in method="POST" instead of methods="POST"

Flask Preventing Form Injection

How can python / flask block foreign form injections?
Consider the following mwe:
app.py
from flask import Flask, request, render template
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def helloworld():
if request.method == 'GET':
return render_template('index.html')
if request.method == 'POST':
print(request.form['info'])
## do something with the info, like write to a database
return 'nothing'
if __name__ == '__main__':
app.run(debug=True)
templates/index.html
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type='text/javascript' src="{{ url_for('static', filename='js/fire.js') }}"></script>
</head>
<body>
<p>Hello world!</p>
</body>
</html>
static/js/fire.js
$(document).click(function() {
// post data to flask
$.post('/', {'info': 'test'});
return false;
};
My questions are:
Is injection possible from a foreign website? Follow-up: how could this be done? (e.g., perhaps via a form that posts to my website url?)
If injection is possible, what can I do in the app.py script to block the injection?
Edit
Here is a very basic script that can be used to test injections against the above flask application. The accepted answer blocks this script:
<!DOCTYPE html>
<html>
<body>
<h2>Malicious Form Injection</h2>
<form action='http://127.0.0.1:5000/' method='post'>
Input 1:<br>
<input name="info" value="mal1"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
app.py
from flask import Flask, request, render template
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
CSRFProtect(app)
app.config['SECRET_KEY'] = 'somethignrandom'
#app.route('/', methods=['GET','POST'])
def helloworld():
if request.method == 'GET':
return render_template('index.html')
if request.method == 'POST': # anything post will autocheck csrf
print(request.form['info'])
## do something with the info, like write to a database
return 'nothing'
if __name__ == '__main__':
app.run(debug=True)
There is no need to pass the secret key to the html template, as CSRFProtect will automatically pass the secret key.
templates/index.html
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<meta name='csrf-token' content="{{ csrf_token() }}">
<script type='text/javascript' src="{{ url_for('static', filename='js/fire.js') }}"></script>
</head>
<body>
<p>Hello world!</p>
</body>
</html>
script.js
$(document).click(function() {
// post data to flask
$.post('/', {'info': 'test', '_csrf_token':$('meta[name="csrf-token"]').attr('content')});
return false;
};

How to Display Image in Flask after a button is pressed

I am new to flask and web development. I want to display an image on a local web server after I press a button on the webpage. I am using Flask.Ive been trying to figure this out for a while and havent been able too so any help would be incredible.
FLASK CODE:
#app.route('/graph_select')
def graph_select():
return render_template('live_stream.html')
#app.route('/read_ph', methods=["GET"])
def ph_plot():
if request.method == "GET":
all_plots.ph_plot()
return render_template('live_stream.html')
#app.route("/read_temp", methods=["GET"])
def temp_plot():
if request.method == "GET":
all_plots.temperature_plot()
return render_template('live_stream.html')
#app.route('/read_distance', methods=["GET"])
def distance_plot():
if request.method == "GET":
all_plots.distance_plot()
return render_template('live_stream.html')
HTML CODE:
<h1>Data Monitoring Station</h1>
<form method="GET"
<button type="button">Temperature Graph</button>
<button type="button">PH Graph</button>
<button type="button">Distance Graph</button>
</form>
<h3><img src="{{ url_for('static', filename='ph_plot.png') }}" width="30%">$
<h3><img src="{{ url_for('static', filename='temperature_plot.png') }}" width="30%">$
<h3><img src="{{ url_for('static', filename='distance_plot.png') }}" width="30%">$
</body>
</html>
TLDR;
I wrote a minimal example on displaying images on button click using Flask and Ajax.
In essence, I just returned the URL of the image to the HTML page and set the src attribute of <img> tag with the returned URL.
app.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('a.html')
#app.route("/getimage")
def get_img():
return "a.jpg"
if __name__ == '__main__':
app.run()
a.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<button type='button' id ='retrieve'>Submit</button>
<img src="" id="myimg" />
</body>
<script>
$(document).ready(function() {
$('#retrieve').click(function(){
$.ajax({
url: "{{ url_for ('get_img') }}",
type: "GET",
success: function(response) {
$("#myimg").attr('src', '/static/' + response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
</html>
You can modify this code as you wish.
Note: The a.html file should be in templates folder and the a.jpg file should be in the static folder.
Hope this helps. Good luck.

How to run a python script in the background on click of html button using flask framework

''' upload.html'''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2 style="color:DodgerBlue;">File Uploader</h2>
<form id = "upload-form" action = "{{ url_for('upload') }}" method="POST"
enctype="multipart/form-data">
<input type = "file" name = "file" accept = "files/*" multiple>
<input type = "submit" value = "submit">
</form>
</body>
</html>
''' app.py'''
import os
from flask import Flask, request, render_template, send_from_directory
app = Flask(__name__)
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
#app.route("/")
def index():
return render_template("upload.html")
#app.route("/upload", methods=["POST"])
def upload():
target = os.path.join(APP_ROOT, 'Athena_XML_files/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("file"):
print(file)
filename = file.filename
destination = "/".join([target, filename])
print(destination)
file.save(destination)
return render_template("complete.html")
#app.route('/run_script')
def run_script():
app.config.from_pyfile("main.py")
return render_template('result.html')
if __name__ == "__main__":
app.run(port=4555, debug=True)
'''complete.html'''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>XML files Uploaded</h1>
<ul><br><br>
<h2><strong>Please click to obtain the result</strong></h2><br><br>
<ul class="nav nav-stacked">
<li role="presentation"><a href="{{ url_for('run_script') }}">CLICK
HERE</a></li>
</ul>
</ul>
</body>
</html>
As the XML files are uploaded and the CLICK HERE button is clicked, main.py file should run in the background for which i have made a function in app.py file to run the main.py file.
Uploading works well, but on click of button the main.py file is not running in the background.
I'm not sure if your idea is a good one. I posted some small solutions, but you should read this article for a better practice.
1) If you want to run an external script from inside flask, you could use subprocess to run a script from the command line.
#app.route('/run-script')
def run_script():
result = subprocess.check_output("python main.py", shell=True)
return render_template('results.html', **locals())
2) If you want to run Python code in background without any return, you could create a thread.
from threading import Thread
#app.route('/run-in-background')
def run_in_background():
run_func()
return redirect(url_for('.index'))
def run_func():
data = { 'some': 'data', 'any': 'data' }
thr = Thread(target=run_async_func, args=[app, data])
thr.start()
return thr
def run_async_func(app, data):
with app.app_context():
# Your working code here!
example_module.do_somthing_with(data)
Not sure if it helps. Both solutions could make a lot mess.
You should read the flask docs.
The app.config.from_pyfile function evaluates configuration data from Python code. This is very different than your question.

File upload using Flask without refresh

I have user interface (angularJS) in which i need to upload a file without refreshing the page.Currently we are using Flask as web application framework.
I changed the index.html to below format so that without using form tags i am trying to read the uploaded file and store it.
Using ngclick method how to read the file from app.py ?
The following is the code snippet(index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<title>Python Flask Bucket List App</title>
<link href="http://bootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
</head>
<body>
<div ng-controller = "myCtrl">
<input type = "file" file-model = "myFile"/>
<button ng-click = "uploadFile()">upload file</button>
</div>
</body>
</html>
code snippet of app.py
from flask import Flask, render_template, json, request
app = Flask(__name__)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/upload/')
def upload_file():
print('uploaded file ',request.FILES['file1'].read())
return render_template('signup.html')
I tried various options but i could not find feasible option.
Thanks
vijay

Categories

Resources