简体   繁体   English

使用烧瓶返回创建的 excel 文件

[英]return a created excel file with flask

I am creating a excel file using openpyxl which I would like to return as a file download (so not saving locally).我正在使用 openpyxl 创建一个 excel 文件,我想将其作为文件下载返回(因此不保存在本地)。

I can create the excel file fine and save it to disk.我可以很好地创建 excel 文件并将其保存到磁盘。 However, I cannot get this file to download.但是,我无法下载此文件。

Attempt 1:尝试1:

import flask_excel as excel

...

create_excel_sheet(data) # internally save the sheet with name sheet.xlsx

output = excel.make_response()
output.headers["Content-Disposition"] = "attachment; filename=" + \
                                        'sheet.xlsx'
output.headers["Content-type"] = "application/vnd.openxmlformats-\
officedocument.spreadsheetml.sheet"

return output

This returns an empty text file with name sheet.xlsx这将返回一个名为 sheet.xlsx 的空文本文件

Attempt 2: wb = create_excel_sheet(data) # return openpyxl workbook尝试 2: wb = create_excel_sheet(data) # return openpyxl workbook

output = excel.make_response(wb)
output.headers["Content-Disposition"] = "attachment; filename=" + \
                                        'sheet.xlsx'
output.headers["Content-type"] = "application/vnd.openxmlformats-\
officedocument.spreadsheetml.sheet"

return output

I don't want to use pyexcel for the data as I need openpyxl to create a fancy excel sheet.我不想将 pyexcel 用于数据,因为我需要 openpyxl 来创建精美的 excel 表。 Obviously if pyexcel and openpyxl communicated that would be fine.显然,如果 pyexcel 和 openpyxl 进行通信就可以了。

any thoughts?有什么想法吗?

Cheers, Mike干杯,迈克

Based on Charlie Clark's hint , I finally settled on the following solution.根据查理克拉克的提示,我最终确定了以下解决方案。

output = make_response(create_sheet(data))
output.headers["Content-Disposition"] = "attachment; filename=" + \
                                        "sheet.xlsx"
output.headers["Content-type"] = \
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

where在哪里

def create_sheet(data):

returns返回

return save_virtual_workbook(wb)

Since I struggled with ambiguity to reassemble fragmented and a little bit old-fashioned code snippets, I want to leave another answer here.由于我在重新组装零散的和有点老式的代码片段时模棱两可,我想在这里留下另一个答案。 This is technically the same but a quite complete code snippet which is a little bit more up to date.这在技术上是相同的,但是一个非常完整的代码片段,它有点更新。

from flask import Response
from openpyxl import Workbook
from openpyxl.writer.excel import save_virtual_workbook

...

@app.route("/download")
def download():
    wb = Workbook()
    
    ...

    return Response(
        save_virtual_workbook(wb),
        headers={
            'Content-Disposition': 'attachment; filename=sheet.xlsx',
            'Content-type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        }
    )


What I did when I faced the same problem is that I wrote a temporary file on the server, I made my create_excel_sheet(data) function to return file name and then send the file back with the flask send_file() function:当我遇到同样的问题时,我所做的是我在服务器上编写了一个临时文件,我让我的create_excel_sheet(data)函数返回文件名,然后使用flask send_file()函数将文件发回:

send_file( create_excel_sheet_and_return_filename(data) )

You can use python modules that create temporary files which are deleted when the process exists and use authorization if security is an issue.您可以使用 python 模块来创建临时文件,当进程存在时这些临时文件会被删除,如果安全是一个问题,则可以使用授权。

That all looks correct.这一切看起来都是正确的。 Are you actually returning the response from your view?您实际上是否从您的视图中返回响应? That wasn't clear in the question, and would explain the problem, I think.我认为这个问题并不清楚,并且可以解释这个问题。

For example:例如:

@app.route('/download_sheet')
def download():
    create_excel_sheet(data)
    output = excel.make_response()
    output.headers["Content-Disposition"] = "attachment; filename=sheet.xlsx"
    output.headers["Content-type"] = "application/vnd.openxmlformats-\
officedocument.spreadsheetml.sheet"
    return output  # Send the response to the user

... ...

<a href="{{ url_for('app.download') }}">Click here for Sheet</a>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM