Bacana, me identifiquei com o post pois recentemente tive esse mesmo problema com a diferença que o relatório que o sistema gera é em pdf ou planilha excel. No meu caso utilizei streaming de dados com generator do python com fastapi e no front-end alterei o fluxo para abrir o download em uma aba separada, dessa forma o browser gerencia o download do arquivo e o fluxo fica livre para o usuário.

Aí sim, é uma otima solução também. Você consegue compartilhar alguma referencia que te ajudou na época?

Eu tentei essa abordagem também, mas não encontrei uma maneira do browser fazer o download via stream, eu ia ter que baixar como stream na memória e depois fazer o download na máquina do usuário, então preferi fazer via fila, salvar no bucket e depois notificar o usuário pra ele baixar o arquivo processado direto do bucket.

Sua solução é muito elegante, cumpre muito bem o papel. Um pequeno exemplo de como eu fiz, adaptei para .csv: ## Python / Fastapi ```python import csv import io import random import string def gerar_dados_csv(tamanho_desejado_mb): data = io.StringIO() writer = csv.writer(data) writer.writerow(["ID", "NAME", "AGE", "COUNTRY"]) total_size = 0 while total_size < tamanho_desejado_mb * 1024 * 1024: id = random.randint(1, 1000) name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=5)) age = random.randint(20, 60) country = random.choice(['Brazil', 'India', 'USA', 'Canada', 'UK']) writer.writerow([id, name, age, country]) chunk = data.getvalue() total_size += len(chunk) data.seek(0) data.truncate(0) yield chunk @router.get('/csv/{tamanho}') async def get_pdf(tamanho: int): nome_arquivo = f'relatorio.csv' headers = {"Content-Disposition": f"attachment; filename={nome_arquivo}", 'x-filename': nome_arquivo} return StreamingResponse(gerar_dados_csv(tamanho), media_type='application/csv', headers=headers) ``` ## Javascript ```javascript /** * Método para realizar download em uma nova aba, com responsabilidade * do processo de download a cargo do browser. * * @param {String} url para download */ async function fileDownload(url) { try { // url completa, com path variables e query params. const _url = `${axiosAPI.defaults.baseURL}${url}` const anchorElement = document.createElement('a') anchorElement.setAttribute("href", _url) anchorElement.setAttribute("target", "_blank") document.body.appendChild(anchorElement) anchorElement.click() document.body.removeChild(anchorElement) } catch (error) { console.log('error: ', error) throw new Error("Erro ao baixar arquivo.") } } ```