使用Flask下载多个CSV?

时间:2015-02-17 18:37:05

标签: python flask

我有一个应用程序,它接收一些信息,使用pandas执行一些计算,并将最终的pandas数据帧转换为CSV,然后使用Flask应用程序下载。如何在一个视图中下载多个CSV?似乎我一次只能回复一个回复。

示例摘录:

def serve_csv(dataframe,filename):
    buffer = StringIO.StringIO()
    dataframe.to_csv(buffer, encoding='utf-8', index=False)
    buffer.seek(0)
    return send_file(buffer,
             attachment_filename=filename,
             mimetype='text/csv')

def make_calculation(arg1, arg2):
   '''Does some calculations.
   input: arg1 - string, arg2- string
   returns: a pandas data frame'''

@app.route('test_app', methods=['GET', 'POST']
def test_app():
    form = Form1()
    if form.validate_on_submit():
    calculated_dataframe = make_calculation(str(form.input_1.data), str(form.input_2.data))
        return serve_csv(calculated_dataframe, 'Your_final_output.csv')
    return render_template('test_app.html', form=form)

所以让我们在上面的例子中说make_calculation返回了两个pandas数据帧。我如何将它们打印成CSV?

4 个答案:

答案 0 :(得分:6)

这是使用Zip files所需的所有代码。它将返回包含所有文件的zip文件。

在我的程序中,我要压缩的所有内容都在output文件夹中,因此我只使用os.walk并将其放在带有write的zip文件中。在返回file之前,您需要关闭,如果您没有关闭,则会返回一个空文件。

import zipfile
import os
from flask import send_file

@app.route('/download_all')
def download_all():
    zipf = zipfile.ZipFile('Name.zip','w', zipfile.ZIP_DEFLATED)
    for root,dirs, files in os.walk('output/'):
        for file in files:
            zipf.write('output/'+file)
    zipf.close()
    return send_file('Name.zip',
            mimetype = 'zip',
            attachment_filename= 'Name.zip',
            as_attachment = True)

html我只需拨打路线:

<a href="{{url_for( 'download_all')}}"> DOWNLOAD ALL </a>

我希望这有助于某人。 :)

答案 1 :(得分:4)

你可以返回一个MIME Multipart响应,一个zip文件或一个TAR球(请注意链接的RFC有点过时,但更容易快速加速,因为它是HTML格式的;官方的是here)。

如果您选择执行MIME多部分响应,那么一个好的起点可能是查看MultipartEncoder中的MultipartDecoderrequests toolbelt;您可以直接使用它们,或者至少使用它们进行子类化/组合以获得您想要的行为。 Zip filesTAR balls可以使用标准库模块实现。

另一种方法是设计您的API,以便您返回JSON,使用标头(或XML元素或JSON字段)来指示其他CSV可以通过其他请求获得,或类似的。

答案 2 :(得分:1)

在@ desfido上面的答案的基础上,这里将是一些不涉及使用zip的代码实现,而是下载两个不同的文件:

from requests_toolbelt import MultipartEncoder

def make_calculation(arg1, arg2):
    '''Does some calculations.
    input: arg1 - string, arg2- string
    puts results in two different dataframes
    and stores them in two different files,
    returns the names of those two files'''
    return filename1, filename2

@app.route('test_app', methods=['GET', 'POST'])
def test_app():
    form = Form1()
    if form.validate_on_submit():
        f1, f2 = make_calculation(str(form.input_1.data), str(form.input_2.data))
        m = MultipartEncoder({
           'field1': (f1, open(f1, 'rb'), 'text/plain'),
           'field2': (f2, open(f2, 'rb'), 'text/plain')
        })
        return Response(m.to_string(), mimetype=m.content_type)
   return render_template('test_app.html', form=form)

答案 3 :(得分:0)

你也可以试试这个,使用 zip 模块 --

import zipfile
from os.path import basename

UPLOAD_PATH = <upload_location>
base_files = ["file1.csv", "file2.csv"]
  
with zipfile.ZipFile(UPLOAD_PATH + 'Test.zip', 'w') as zipF:
    for file in base_files:
        zipF.write(UPLOAD_PATH + file, basename(UPLOAD_PATH + file), compress_type=zipfile.ZIP_DEFLATED)
zipF.close()
return send_file(METAFILE_UPLOADS+'Test.zip', mimetype='zip', attachment_filename='Test.zip', as_attachment=True)