I am trying to make a web app that reads a selected file into the program and does calculations on the data inputted.
index.html
<body>
<div class="container">
<hr/>
<div>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file"><br /><br />
<input type="submit" value="Upload">
</form>
</div>
</div>
</body>
python file
#app.route('/')
def index():
return render_template('index.html')
#app.route('/upload', methods=['GET', 'POST'])
def upload():
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
text_file = open(filename,"r")
Data = text_file.read()
return render_template('base.html',filename=filename)
Here I'm getting the file then saving it locally then opening it and getting the data. I want to get the "Data" into other functions to do calculations on. How do I go about getting my data to other functions?
I would like to have a page saying X file was loaded in then be able to click the tabs on my web app to run the calculations on said file.
Related
i am using python with flask. i want to send variable to html. getting html output.
ı pass filename variable with render_template. but i dont show in output variable in html
this my python code
#app.route('/', methods=['POST'])
def upload_image():
#cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No image selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
print('upload_image filename: ' + filename)
#cursor.execute("INSERT INTO upload (title) VALUES (%s)", (filename,))
#conn.commit()
#os.remove(os.path.join(app.config['UPLOAD_FOLDER'], filename))
filenamea = 'result_'+str(uuid.uuid4())+'.png'
input_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
output_path = os.path.join(app.config['UPLOAD_FOLDER'], filenamea)
#session = new_session()
input = Image.open(input_path)
output = remove(input)
output.save(output_path)
flash('Image successfully uploaded and displayed below')
return render_template('index.html', filename=filename)
else:
flash('Allowed image types are - png, jpg, jpeg, gif')
return redirect(request.url)
#app.route('/display/<filename>')
def display_image(filename):
#print('display_image filename: ' + filename)
return redirect(url_for('static', filename='uploads/' + filename), code=301)
this my html code:
<body>
{% if filename %}
<div>
<img src="{{url_for('display_image', filename=filename)}}">
</div>
{% endif %}
<div class="wrapper">
<header>Image Backgroud Cleaner</header>
<form action="#">
<input class="file-input" type="file" name="file" multiple hidden>
<i class="fas fa-cloud-upload-alt"></i>
<p>Browse File to Upload</p>
</form>
<section class="progress-area"></section>
<section class="uploaded-area"></section>
</div>
<script src="{{url_for('static', filename='script2.js')}}"></script>
</body>
output
The excerpts above are evidently an incomplete piece of a whole application. Ideally, queries should be reduced to a minimal reproducible example that can be simulated without depending on the rest of your application. This isn't said to be critical but rather to engender your patience and grace if contributors like me have had to make assumptions about your specific scenario to answer your question.
The most pivotal assumption I've made is that the included html text is the template named index.html. Incidentally, it is importing script2.js. Only you know what that script is doing (not to belabor the point) so please pardon if you've already addressed the following suggestions in that javascript file or elsewhere.
Neither of the routes posted above have a GET method that will return index.html. <form action="#"> suggests that you are using the upload_image route for both the GET and POST of index.html, so the absence of a corresponding route supporting the GET method is very likely one of the problems that you're facing.
There are at least two approaches you could try to add a corresponding route supporting the GET method that returns index.html:
Method A - Update upload_image route to support GET method
#app.route('/', methods=['GET','POST'])
def upload_image():
if request.method == 'POST':
# All the POST logic goes here
else:
# All the GET logic goes here
return render_template('index.html')
Method B - Create a corresponding new route
#app.route('/upload_page', methods=['GET'])
def upload_page():
return render_template('index.html')
A reason for preferring method B is that you can leverage the upload_image route elsewhere to upload files in your application in different templating contexts if you haven't constrained it to index.html. I've favored method B in my index.html example below. Note that I've changed <form action="#" to <form action="/" so that it routes explicitly to the base route on POST.
Not only do you need to add a route that supports the GET method and returns index.html, but you also need to add method="post" enctype="multipart/form-data" as attributes of the form in index.html. Otherwise it will always default as a GET request and the intended POST will fail.
The hidden attribute is preventing the file input from rendering. If you're not intentionally using it for an unstated purpose, remove it.
You also need a submit input or other interface of some sort in index.html to submit the upload form.
Depending on if and how you configured an upload folder path, you may be running into issues with the route #app.route('/display/<filename>'). You actually don't need this route at all if you leverage the default by adding a folder named static in your application root directory. You need only change the url_for argument from display_image to static for this to work.
Given the above adjustments, index.html now looks like this:
<body>
{% if filename %}
<div>
<img src="{{url_for('static', filename=filename)}}">
</div>
{% endif %}
<div class="wrapper">
<header>Image Backgroud Cleaner</header>
<form action="/" method="post" enctype=multipart/form-data>
<input class="file-input" type="file" name="file" multiple>
<input type="submit">
<i class="fas fa-cloud-upload-alt"></i>
<p>Browse File to Upload</p>
</form>
<section class="progress-area"></section>
<section class="uploaded-area"></section>
</div>
<script src="{{url_for('static', filename='script2.js')}}"></script>
</body>
With these adjustments, you now should be getting the output variable filename that your question stated you were not getting in index.html and the <img> preview of filename should be visible in the rendered page.
This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Get the data received in a Flask request
(23 answers)
Closed 2 months ago.
I'm working on an upload file function for my web tool and I'm facing an issue. The problem is that Flask is not receiving the files from the HTML form. I have already set the route, and created the form tag accordingly to what is required like the method POST and still not working. Am I doing anything wrong?
HTML
<form action="/" method="POST" enctype="multipart/form-data" class="form-horizontal">
<div class="row form-group">
<div class="col-12 col-md-12">
<div class="control-group" id="fields">
<label class="control-label" for="field1">
Requests
</label>
<div class="controls">
<div class="entry input-group upload-input-group">
<input class="form-control" name="fields[]" type="file">
<button class="btn btn-upload btn-success btn-add" type="button">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<button class="btn btn-primary" type="submit" value="Submit">Upload</button>
</div>
</div>
</div>
</form>
Python/Flask
import os
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
app=Flask(__name__)
app.secret_key = "secret key"
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
path = os.getcwd()
# file Upload
UPLOAD_FOLDER = os.path.join(path, 'uploads')
if not os.path.isdir(UPLOAD_FOLDER):
os.mkdir(UPLOAD_FOLDER)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
ALLOWED_EXTENSIONS = set(['xlsx', 'xls'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('index.html')
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are xlsx and xls')
return redirect(request.url)
if __name__ == "__main__":
app.run(host = '127.0.0.1',port = 5000, debug = False)
Try changing the input name to file instead fields[]
<input class="form-control" name="file" type="file">
I am making a webapp for OCR on document with layoutlm using flask, website has upload system that accepts images and documents which are later processed by a python file for OCR which returns a JSON containing 'key' as field name like 'Name', 'DOB' and value as corresponding answer to the field as 'Akshit', '17/02/2002'. I have got the upload system working but am not able to figure out how I display these values into my HTML webpage. Can you please help?
app.py:-
from flask import Flask
UPLOAD_FOLDER = r'path\to\upload\folder'
app = Flask(__name__)
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
main.py :-
#import magic
import urllib.request
from invoice_docquery import ret_scores
from app import app
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = set(['pdf', 'png', 'jpg', 'jpeg'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('index.html')
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
json_ans = ret_scores(filename) # Performs OCR and returns json containing key as field names and value as its corresponding answers
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are pdf, png, jpg, jpeg')
return redirect(request.url)
if __name__ == "__main__":
app.run()
HTML code so far (index.html):-
<!doctype html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</p>
<form method="post" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="file" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" value="Submit">
</p>
</form>
function 'ret_scores' in main.py returns the required json for which I want to display its values in the HTML webpage
Do let me know if any additional information is required
It's difficult to diagnose exactly what your issue is as you didn't explain what output you're getting (error message? no content showing?), but the issue appears to be in the way you're trying to use the jinja template, in particular in the line:
{% with messages = get_flashed_messages() %}
What is get_flashed_messages() and how does the template know where to find it?
You pass information to templates as parameters in render_template, so your #app.route('/') will need to contain a line like:
return render_template('index.html', messages)
Passing variables between routes gets messy and confusing, so I recommend using session variables to store the information that you will pass to the template.
I've rewritten your code to demonstrate the basic flow, but please don't expect it to run first time as I haven't run it to test. There may still be some debugging to do but hopefully it should demonstrate the general idea and get you moving in the right direction.
app.py looks fine as-is.
main.py:
#import magic
import urllib.request
from invoice_docquery import ret_scores
from app import app
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = set(['pdf', 'png', 'jpg', 'jpeg'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
if session['messages']:
return render_template('index.html', messages=session['messages'])
else:
return render_template('index.html', messages={})
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
session['messages'] = ret_scores(filename) # Performs OCR and returns json containing key as field names and value as its corresponding answers
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are pdf, png, jpg, jpeg')
return redirect(request.url)
if __name__ == "__main__":
app.run()
index.html:
<!doctype html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</p>
<form method="post" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="file" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" value="Submit">
</p>
</form>
Feel free to ask any question is in the comments and I'll do my best to help when I can.
I have a python script that reads content of 2 files, and maps the data and outputs a csv. Currently the code reads the path of the files however I want it so that the user uploads the file and the code reads the files and generates the csv.
I started the flask code that uploads the multiple files but I need help saving the files to variables that my python script would be able to read.
My python script:
user_input = input("Enter the path of First File : ")
user_input2 = input("Enter the path of Second File : ")
assert os.path.exists(user_input), "Invalid file at, " + str(user_input)
f = open(user_input, 'r')
f2 = open(user_input2, 'r')
content = f.read()
content2 = f2.read()
def parse_value(txt):
reclines = []
for line in txt.split('\n'):
if ':' not in line:
if reclines:
yield reclines
reclines = []
else:
reclines.append(line)
def parse_fields(reclines):
res = {}
for line in reclines:
key, val = line.strip().rstrip(',').split(':', 1)
res[key.strip()] = val.strip()
return res
res = []
for rec in parse_value(content):
res.append(parse_fields(rec))
res2 = []
for rec in parse_value(content2):
res2.append(parse_fields(rec))
df = pd.json_normalize(res)
df2 = pd.json_normalize(res2)
flask codes for uploading files:
upload.py
import os
import magic
from app import app
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = set(['tpi'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('button.html')
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
print(request.__dict__)
# check if the post request has the file part
if 'sfile' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['sfile']
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are tpi')
return redirect(request.url)
if __name__ == "__main__":
app.run(host="0.0.0.0", port = 5000, debug=True)
button.html
<!doctype html>
<title>Python Flask File Upload Example</title>
<h2>Upload First File</h2>
<form method="post" name="sform" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="sfile" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" name="ssubmit" value="Submit">
</p>
</form>
<h2>Upload Second File</h2>
<form method="post" name="wform" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="sfile" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" name="wsubmit" value="Submit">
</p>
</form>
How can I fix the flask codes to save the first uploaded file to variable f and and second uploaded variable to f2?
What you're looking for is the .read() method.
with open(user_input, 'r') as file:
file_one = file.read()
with open(user_input, 'r') as file:
file_two = file.read()
You may need to instantiate the file vars outside the context manager, but something like this should get you started
I have a multi-upload form in flask.
<form class="form-group" action="{{ url_for('load') }}" method="POST" enctype="multipart/form-data">
<input id="file-picker" type="file" name="file1"><br>
<input id="file-picker" type="file" name="file2"><br>
<input id="file-picker" type="file" name="file3"><br>
<input id="file-picker" type="file" name="file4"><br>
</form>
This is how i handle data from it:
#app.route("/load", methods=['GET', 'POST'])
def load():
if request.method == 'POST':
file = request.files.get("file1")
file_name = secure_filename(file.filename)
im = Image.open(file)
im.save(file_name)
upload(photo=file_name)
The upload() uploads the image from the form to s3.I dont want to use request.getlist('files'), because this way, retrieving them later on is easier.
I save the uploaded files in a static folder before uploading them to amazon s3. If I wanted to upload only 3 out of these 4 files, I get IOError: [Errno 22].
Is there any way to ignore this error? i.e Can I make it such that I can upload only one/two/three instead of compulsorily uploading all 4 files every time?
All right, so here is what I did..turned out to be pretty simple. Thanks for the tip #furas
#app.route("/load", methods=['GET', 'POST'])
def load():
if request.method == 'POST':
files = request.files.getlist("file")
for file in files:
file.seek(0, os.SEEK_END)
if file.tell() == 0:
pass
else:
file_name = secure_filename(file.filename)
upload(p=file_name)