I am building a small Flask app in Windows 11. In my app, I take a string from a user, convert it to a text file, and send the user that text file in a subfolder of 'static'. However, the key thing I want to do is send that file as an anchor tag that downloads on clicking.
I want the download link to appear as a clickable link on the original webpage (that is have a one page site that doesn't reroute), and I do not want to send a direct download (Flask's send_file function).
My Flask App (app.py):
#Package Imports
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
import random
#Create Flask Form
#Create the Flask form here.
class MyForm(FlaskForm):
text_field = StringField('Write here.', validators=[DataRequired()])
submit_field = SubmitField('Submit')
#This function makes a text file with the user's text.
def make_text_file(my_string):
filename = 'static/text_files/{}.txt'.format(random.randint(1, 1000000))
with open(filename, 'w') as file:
file.write(my_string)
return '/'.join(filename.split('/')[1:])
#Create the Flask app here.
app = Flask(__name__)
app.config['SECRET_KEY'] = 'ABCDEFG'
@app.route('/', methods=['GET', 'POST'])
def index():
result = False
form = MyForm()
if request.method == 'POST':
text = request.form['text_field']
result = make_text_file(text)
return render_template('index.html', form=form, result=result)
return render_template('index.html', form=form, result=result)
My HTML Jinja2/Template (index.html):
<html>
<body>
<form method="POST" action="{{ url_for('index') }}">
<div class='form-div'>
{{ form.csrf_token }}
<div>{{ form.text_field }}</div>
<div>{{ form.submit_field }}</div>
</div>
</form>
<div id='result-link'>
{% if result == False %}
<div></div>
{% else %}
<a href="{{ url_for('static', filename=result) }}" download>Here is your file.</a>
{% endif %}
</div>
</body>
</html>
I have tried the following solutions but they did not work:
- I used the @after_this_request decorator from Flask, but since my route function handles both 'GET' and 'POST' requests, how do I specify that a specific function (namely deleting the file) should happen after a 'POST' request? To my knowledge, this solution only works in Linux. While I do plan on serving the end website in a Linux server, is there a way to test the filed deletion mechanism in Windows?
- I tried WebSockets, namely Flask-SocketIO, and incorporated this into my code as well. However, I receive a "The WebSocket transport is not available, you must install a WebSocket server that is compatible with your async mode to enable it. See the documentation for details. (further occurrences of this error will be logged with level INFO)". I am running a Flask development server in the virtual environment and am unsure how to set up a production server to test whether the WebSocket strategy works.
- While the example I provide is text files, I eventually want to be able to serve video files to clients. Would reading the file into memory, per the solution here be a feasible solution?