【问题标题】:Excel export with Flask server and xlsxwriter使用 Flask 服务器和 xlsxwriter 导出 Excel
【发布时间】:2020-01-08 15:52:44
【问题描述】:

所以我过去一直使用 XLSXWriter 来导出一个包含一个选项卡的 excel 文件,该选项卡填充了两个 pandas 数据框。过去我只将文件导出到用户计算机上的本地路径,但我正在转换到 Web 界面。

我想要的输出是与下面的代码具有相同的 excel 文件,但在内存中创建并发送给用户,供他/她通过 Web 界面下载。我已经看到了很多 Django 和 StringIO,但我正在寻找可以与 Flask 一起使用的东西,但我找不到任何真正有效的东西。

有人熟悉这个问题吗?

提前致谢!

xlsx_path = "C:\test.xlsx"
writer = pd.ExcelWriter(xlsx_path, engine='xlsxwriter')

df_1.to_excel(writer,startrow = 0, merge_cells = False, sheet_name = "Sheet_1")
df_2.to_excel(writer,startrow = len(df_1) + 4, merge_cells = False , sheet_name = "Sheet_1")                             

workbook = writer.book
worksheet = writer.sheets["Sheet_1"]
format = workbook.add_format()
format.set_bg_color('#eeeeee')
worksheet.set_column(0,9,28)

writer.close()

【问题讨论】:

  • 您使用的是哪个版本的 Pandas?
  • 我使用的是 Pandas 0.17.1 和 Python 3.5.1

标签: python pandas flask xlsxwriter


【解决方案1】:

以下 sn-p 适用于 Win10 和 Python 3.4 64 位。

Pandas ExcelWriter 写入BytesIO 流,然后通过Flasksend_file 发送回用户。

import numpy as np
import pandas as pd
from io import BytesIO
from flask import Flask, send_file

app = Flask(__name__)
@app.route('/')

def index():

    #create a random Pandas dataframe
    df_1 = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=list('ABCD'))

    #create an output stream
    output = BytesIO()
    writer = pd.ExcelWriter(output, engine='xlsxwriter')

    #taken from the original question
    df_1.to_excel(writer, startrow = 0, merge_cells = False, sheet_name = "Sheet_1")
    workbook = writer.book
    worksheet = writer.sheets["Sheet_1"]
    format = workbook.add_format()
    format.set_bg_color('#eeeeee')
    worksheet.set_column(0,9,28)

    #the writer has done its job
    writer.close()

    #go back to the beginning of the stream
    output.seek(0)

    #finally return the file
    return send_file(output, attachment_filename="testing.xlsx", as_attachment=True)

app.run(debug=True)

参考资料:

【讨论】:

  • 这是一个完美的解决方案,就像一个魅力!谢谢!
  • 我尝试了同样的方法,也可以得到'xlsx'文件但无法打开它,下载后文件已损坏。
  • @arshpreet 您是否尝试先在本地保存 Excel 文件并查看是否有效?
  • @MaximilianPeters 否则从 send_file() 它仍然无法正常工作,从 send_file() 有什么问题吗?
  • @MaximilianPeters 解决了,问题出在我的 flask_configuration 文件上,现在我使用 Flask 仅使用以下方法发送文件:application.config["USE_X_SENDFILE"] = True
【解决方案2】:

你可以使用类似于this的东西:

from flask import Flask, send_file
import io

myio = io.StringIO()

with open(xlsx_path, 'rb') as f:
    data = f.read()

myio.write(data)
myio.seek(0)

app = Flask(__name__)

@app.route('/')
def index():
    send_file(myio,
              attachment_filename="test.xlsx",
              as_attachment=True)

app.run(debug=True)

您可能还想使用 tempfile 编写您的 excel 文件

【讨论】:

    【解决方案3】:

    如果您希望 xlsx 文件作为响应而不将其存储在服务器端。可以使用下面的代码sn-p。

    from flask import Flask
    
    app = Flask(__name__)
    
    data = [[1, 2], [3, 4]]
    
    
    @app.route('/')
    def get_xslx_for_data():
        try:
            response = Response()
            response.status_code = 200
            output = StringIO.StringIO()
            workbook = xlsxwriter.Workbook(output, {'in_memory': True})
            worksheet = workbook.add_worksheet('hello')
            for i, d in enumerate(data):
                for j, res in enumerate(d):
                    worksheet.write(i, j, res)
            workbook.close()
            output.seek(0)
            response.data = output.read()
            file_name = 'my_file_{}.xlsx'.format(
                datetime.now().strftime('%d/%m/%Y'))
            mimetype_tuple = mimetypes.guess_type(file_name)
            response_headers = Headers({
                'Pragma': "public",  # required,
                'Expires': '0',
                'Cache-Control': 'must-revalidate, post-check=0, pre-check=0',
                'Cache-Control': 'private',  # required for certain browsers,
                'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'Content-Disposition': 'attachment; filename=\"%s\";' % file_name,
                'Content-Transfer-Encoding': 'binary',
                'Content-Length': len(response.data)
            })
    
            if not mimetype_tuple[1] is None:
                response.update({
                    'Content-Encoding': mimetype_tuple[1]
                })
            response.headers = response_headers
            response.set_cookie('fileDownload', 'true', path='/')
            return response
        except Exception as e:
            print(e)
    
    
    if __name__ == '__main__':
        app.run()
    

    【讨论】:

      猜你喜欢
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 2017-08-17
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多