Return a Download and Rendered Page in One Flask Response

Return a download and rendered page in one Flask response

You cannot return multiple responses to a single request. Instead, generate and store the files somewhere, and serve them with another route. Return your rendered template with a url for the route to serve the file.

@app.route('/database')
def database():
# generate some file name
# save the file in the `database_reports` folder used below
return render_template('database.html', filename=stored_file_name)

@app.route('/database_download/<filename>')
def database_download(filename):
return send_from_directory('database_reports', filename)

In the template, use url_for to generate the download url.

<a href="{{ url_for('database_download', filename=filename) }}">Download</a>

How to download file and redirect user to another webpage using flask?

In my opinion it is not possible with flask to serve a file and redirect in the same route.

If you want to send the file and then delete it, I recommend this answer.

If the user should give consent to delete the file, I suggest implementing it with javascript.

from flask import Flask
from flask import render_template, send_from_directory

app = Flask(__name__)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/download')
def download():
fname = 'example.jpg'
return send_from_directory(app.static_folder, fname)

@app.route('/remove')
def remove():
# remove file here!
return render_template('remove.html')
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
</head>
<body>

<button id="download">Download</button>
<script>
(function() {

const save = (data, filename) => {
const elem = document.createElement('a');
elem.href = URL.createObjectURL(data);
elem.download = filename;
elem.click();
};

const download = (url, callback) => {
fetch(url)
.then(res => res.blob())
.then(data => {
callback(data);
});
}

const elem = document.querySelector('#download');
elem.addEventListener('click', (evt) => {
download('/download', (data) => {
save(data, 'example.jpg');

const shouldDeleteFile = confirm("Want to delete?");
if (!shouldDeleteFile) return;

location.href = '/remove';
});
});

})();
</script>

</body>
</html>

How to render a template and send a file simultaneously with flask

Short answer: No. You cannot return different responses at once, obviously.

The quick and dirty solution would be to return the HTML response with your "waiting.html" template, and from this template add some javascript to launch the download.

NB this has nothing to do with flask BTW, you'd have the very same behaviour with any server-side language/techno. It's just how HTTP works.

How to render template sent as response from Flask app in ajax?

Import jsonify and url_for from flask:

from flask import jsonify, url_for

And try returning like this to the ajax call:

@app.route("/execution_pipeline", methods=['POST', 'GET'])
def execution_pipeline():
try:
if request.method == 'POST':
inputMap = request.get_json()
print(inputMap)
###I have my code here###
return jsonify({'redirect': url_for('demo.html', location=minio_results_file_location)})


except ReferenceError as e:
return "It is a {} Provide proper referaece of file path"

Flask: unable to serve rendered pages from specific directory

The following example shows you how you can use FlatPages to list, display and offer files for download. The markdown code is rendered beforehand and integrated into the specified or the default template.

from flask import Flask
from flask import render_template, send_file
from flask_flatpages import FlatPages
from io import BytesIO
import os

app = Flask(__name__)
# Optional configuration here!
pages = FlatPages(app)

# ...

# List all available pages.
@app.route('/contents')
def contents():
return render_template('contents.html', pages=pages)

# Display the rendered result.
@app.route('/page/<path:path>')
def page(path):
page = pages.get_or_404(path)
template = page.meta.get('template', 'flatpage.html')
return render_template(template, page=page)

# Download the rendered result.
@app.route('/download/<path:path>')
def download(path):
page = pages.get_or_404(path)
template = page.meta.get('template', 'flatpage.html')
return send_file(
BytesIO(str(render_template(template, page=page)).encode()),
as_attachment=True,
attachment_filename=f'{os.path.basename(path)}.html'
)

templates/contents.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<ul>
{% for page in pages %}
<li>
[<a href="{{ url_for('download', path=page.path) }}">Download</a>] -
<a href="{{ url_for('page', path=page.path) }}">{{ page.title }}</a>
</li>
{% endfor %}
</ul>
</body>
</html>

templates/flatpage.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ page.title }}</title>
</head>
<body>
{{ page }}
</body>
</html>

pages/Special_Data/ncs1.html

title: Hello
published: 2010-12-22

Hello, *World*!

Lorem ipsum dolor sit amet

If you want to use a different template for rendering, you can define one within the metadata based on the file name. Add the following below published and a suitable template within the templates folder.

template: mytemplate.html


Related Topics



Leave a reply



Submit