如何从 Falcon resp.stream 获取 .xlsx 文件
How to get an .xlsx file from a Falcon resp.stream
我正在尝试从 API 中获取生成的 .xlsx
文件。
我在后端有以下代码:
from io import BytesIO
from openpyxl import Workbook
@api_resource('/get_report')
class Report:
@auth_required()
def on_get(self, req, resp):
wb = Workbook()
ws = wb.active
ws.title = "report"
ws['C9'] = 'hello world'
f = BytesIO()
wb.save(f)
f.seek(0)
resp.stream = f
resp.content_type = \
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
以及前端的以下代码:
ReportsAPI.getReport(filters).then(resp => {
openXLS([resp.data], `report.xlsx`);
});
function openXLS(blob_data, filename) {
let blob = new Blob(blob_data, {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
let url = window.URL.createObjectURL(blob);
let link = document.createElement("a");
document.body.appendChild(link);
link.style = "display: none";
link.href = url;
link.download = filename;
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
我正在通过 API 请求下载文件,但文件已损坏。如果我将文件保存在后端的文件系统中 (```wb.save('test.xlsx')`
), the file opens without problems.
I tried to save the file as indicated in the documentation for openpyxl, but it does not work.
...
from tempfile import NamedTemporaryFile
wb = Workbook()
with NamedTemporaryFile() as tmp:
wb.save(tmp.name)
tmp.seek(0)
resp.stream = BytesIO(tmp.read())
我做错了什么?
在终端 file -bi filename.xlsx
上正常文件 returns application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary
, 但在损坏的文件上 returns application/zip; charset=binary
我试图从终端向 API 发出请求
http GET 'http://127.0.0.1:8000/api/v1/get_report' > test.xlsx
而且文件没有损坏。看来问题出在前端。
在我看来,问题出在编码上,但我无法确定。
尝试将 header 设置为您的回复,如下所示:
def on_get(self, req, resp):
wb = Workbook()
ws = wb.active
ws.title = "report"
ws['C9'] = 'hello world'
f = BytesIO()
wb.save(f)
f.seek(0)
filename = 'sample.xlsx'
resp.stream = f
resp.content_type = \
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
resp.set_header("Content-Disposition", f"attachment; filename={filename}")
问题出在我对 api 的请求中,我使用 axios,默认情况下它总是处理 JSON 中的数据。只需要将响应类型设置为 arraybuffer
class ReportsAPI {
getReport(filters) {
return instance.get(`/get_report`, {
params: { ...filters },
responseType: "arraybuffer"
});
}
}
我正在尝试从 API 中获取生成的 .xlsx
文件。
我在后端有以下代码:
from io import BytesIO
from openpyxl import Workbook
@api_resource('/get_report')
class Report:
@auth_required()
def on_get(self, req, resp):
wb = Workbook()
ws = wb.active
ws.title = "report"
ws['C9'] = 'hello world'
f = BytesIO()
wb.save(f)
f.seek(0)
resp.stream = f
resp.content_type = \
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
以及前端的以下代码:
ReportsAPI.getReport(filters).then(resp => {
openXLS([resp.data], `report.xlsx`);
});
function openXLS(blob_data, filename) {
let blob = new Blob(blob_data, {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
let url = window.URL.createObjectURL(blob);
let link = document.createElement("a");
document.body.appendChild(link);
link.style = "display: none";
link.href = url;
link.download = filename;
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
我正在通过 API 请求下载文件,但文件已损坏。如果我将文件保存在后端的文件系统中 (```wb.save('test.xlsx')`
), the file opens without problems.
I tried to save the file as indicated in the documentation for openpyxl, but it does not work.
...
from tempfile import NamedTemporaryFile
wb = Workbook()
with NamedTemporaryFile() as tmp:
wb.save(tmp.name)
tmp.seek(0)
resp.stream = BytesIO(tmp.read())
我做错了什么?
在终端 file -bi filename.xlsx
上正常文件 returns application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary
, 但在损坏的文件上 returns application/zip; charset=binary
我试图从终端向 API 发出请求
http GET 'http://127.0.0.1:8000/api/v1/get_report' > test.xlsx
而且文件没有损坏。看来问题出在前端。
在我看来,问题出在编码上,但我无法确定。
尝试将 header 设置为您的回复,如下所示:
def on_get(self, req, resp):
wb = Workbook()
ws = wb.active
ws.title = "report"
ws['C9'] = 'hello world'
f = BytesIO()
wb.save(f)
f.seek(0)
filename = 'sample.xlsx'
resp.stream = f
resp.content_type = \
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
resp.set_header("Content-Disposition", f"attachment; filename={filename}")
问题出在我对 api 的请求中,我使用 axios,默认情况下它总是处理 JSON 中的数据。只需要将响应类型设置为 arraybuffer
class ReportsAPI {
getReport(filters) {
return instance.get(`/get_report`, {
params: { ...filters },
responseType: "arraybuffer"
});
}
}