This took me ages to figure out, and it was tough getting a simple straightforward answer…
BTW – I’m assuming that you know all the Flask basics, so I won’t be covering that. If you don’t, I suggest you go through their amazing tutorial.
This is what I want:
- I want my web app to read a file (not upload it) and do stuff with it in python.
- Also, I am using Flask to build my web app
How did I do it?
Once you set up the flask app, go to your __init__.py
file and add two app routes or pages. One for uploading and the other for displaying what has been uploaded.
This is what it should look like
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
@app.route('/upload')
def upload_file():
return 'stuff to be uploaded'
@app.route('/display')
def display_content():
return 'content to be displayed'
These are just place holders at the moments. Let’s sort out the HTML first.
First, we go for the upload page. This one doesn’t really have to be anything special, simple HTML will do.
I am going to use the following HTML for my upload page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Upload file</title>
</head>
<body>
<form action="/display" enctype="multipart/form-data" method="POST">
<input type="file" name="inputfile">
<input type="submit" value= "submit">
</form>
</body>
</html>
There are several things here that are important. First, action
has been set to the display
page, enctype
has been set to multipart/form-data
which is important for handling files. Lastly, the input name for the file has been set to inputfile
.
Next we create a simple HTML template to display the content of the file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Display</title>
</head>
<body>
</body>
{{ file_content }}
</html>
Now let’s go back to the __init__.py
file and change our upload
and display
pages.
# add a couple more imports
from flask import Flask, render_template, request
# upload page displays HTML template file only
@app.route('/upload')
def upload_file():
return render_template('upload.html')
# reader page is where it all happens
@app.route('/display', methods=['GET','POST'])
def display_content():
results = request.files['inputfile'].read().decode('utf-8')
return render_template('display.html', file_content=results)
The upload
page now renders the upload HTML page with the form in it, not much to explain.
The display
app.route is where all the magic happens. First we add the GET
and POST
methods to the app.route
. Then get the relevant data with request
, to which we add files
(since we’re after the file itself) followed by the input name – in this case inputfile
. Now that we have the file we can .read()
it. But the data is binary, so we have to .decode('UTF-8')
to turn it to string so we can then pass it through to our template.
Took me an entire morning to figure all of this out. Very upset with how easy it actually is.
A small waring: This does NOT include validation or security. I’m only using this myself locally. Don’t do this if you are genuinely thinking about deploying.