Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

399
Visualizações
Best way to create a download link for a file in Flask?

In my project, when a user clicks a link, an AJAX request sends the information required to create a CSV. The CSV takes a long time to generate and so I want to be able to include a download link for the generated CSV in the AJAX response. Is this possible?

Most of the answers I've seen return the CSV in the following way:

return Response(
        csv,
        mimetype="text/csv",
        headers={"Content-disposition":
                 "attachment; filename=myplot.csv"})

However, I don't think this is compatible with the AJAX response I'm sending with:

return render_json(200, {'data': params})

Ideally, I'd like to be able to send the download link in the params dict. But I'm also not sure if this is secure. How is this problem typically solved?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

I think one solution may the futures library (pip install futures). The first endpoint can queue up the task and then send the file name back, and then another endpoint can be used to retrieve the file. I also included gzip because it might be a good idea if you are sending larger files. I think more robust solutions use Celery or Rabbit MQ or something along those lines. However, this is a simple solution that should accomplish what you are asking for.

from flask import Flask, jsonify, Response
from uuid import uuid4
from concurrent.futures import ThreadPoolExecutor
import time
import os
import gzip

app = Flask(__name__)

# Global variables used by the thread executor, and the thread executor itself
NUM_THREADS = 5
EXECUTOR = ThreadPoolExecutor(NUM_THREADS)
OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))

# this is your long running processing function
# takes in your arguments from the /queue-task endpoint
def a_long_running_task(*args):
    time_to_wait, output_file_name = int(args[0][0]), args[0][1]
    output_string = 'sleeping for {0} seconds. File: {1}'.format(time_to_wait, output_file_name)
    print(output_string)
    time.sleep(time_to_wait)
    filename = os.path.join(OUTPUT_DIR, output_file_name)
    # here we are writing to a gzipped file to save space and decrease size of file to be sent on network
    with gzip.open(filename, 'wb') as f:
        f.write(output_string)
    print('finished writing {0} after {1} seconds'.format(output_file_name, time_to_wait))

# This is a route that starts the task and then gives them the file name for reference
@app.route('/queue-task/<wait>')
def queue_task(wait):
    output_file_name = str(uuid4()) + '.csv'
    EXECUTOR.submit(a_long_running_task, [wait, output_file_name])
    return jsonify({'filename': output_file_name})

# this takes the file name and returns if exists, otherwise notifies it is not yet done
@app.route('/getfile/<name>')
def get_output_file(name):
    file_name = os.path.join(OUTPUT_DIR, name)
    if not os.path.isfile(file_name):
        return jsonify({"message": "still processing"})
    # read without gzip.open to keep it compressed
    with open(file_name, 'rb') as f:
        resp = Response(f.read())
    # set headers to tell encoding and to send as an attachment
    resp.headers["Content-Encoding"] = 'gzip'
    resp.headers["Content-Disposition"] = "attachment; filename={0}".format(name)
    resp.headers["Content-type"] = "text/csv"
    return resp


if __name__ == '__main__':
    app.run()
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda