day19-python生成文件并提供下载踩的坑
现在有一个生成文件并提供下载的需求,原代码为(csdn一个博客的):
# app.py
from flask import send_file
import xlsxwriter
@app.route("/students/v1.0/excel", methods=["GET"])
def students_excel():
"""1. 生成表头 2. 生成数据 3. 个性化合并单元格,修改字体属性、修改列宽 3. 返回给前端"""
fp = io.BytesIO() # 生成一个BytesIO对象
book = xlsxwriter.Workbook(fp) # 可以认为创建了一个Excel文件
worksheet = book.add_worksheet('students_message') # 增加一个sheet
# 1. 生成表头
header_list = ["姓名", "年龄", "年级"]
for col, header in enumerate(header_list):
worksheet.write(0, col, header) # 行(从0开始), 列(从0开始), 内容
# 2. 生成数据
students_data = [("小王", 12, "7年级"), ("小明", 11, "6年级")]
for row_number, row_tuple in enumerate(students_data):
for col, per_student_info in enumerate(row_tuple):
worksheet.write(col+1, col, per_student_infor) # 遍历导入每个学生的每个信息
# 3. 个性化合并单元格,修改字体属性、修改列宽
# 定义格式实例, 16号字体,加粗,水平居中,垂直居中,红色字体
my_format = book.add_format({'font_size': 16, 'bold': True, 'align': 'center', 'valign': 'vcenter', "font_color": "red"})
worksheet.merge(len(students_data+1, students_data+2, 1, 5, "合并单元格内容", my_format))
book.close()
fp.seek(0)
return send_file(fp, attachment_filename= '学生信息.xlsx', as_attachment=True)
但是实际使用时,会发现第二次下载的文件与第一次下载的文件内容相同。
粗略排查了一下代码,认为问题是写在内存当中每次的内容都一样
但是fp.seek(0)这一操作按理应该把指针指向了最开始的位置,不应该出现这样的问题
后来我觉得是send_file(fp, attachment_filename= '学生信息.xlsx', as_attachment=True)中使用了fp,将指针又指向了文件的尾部(还是觉得不合理,按理说这样会内容变多,而不是与之前一样)
于是又百度去找别的方法,但是大多数都是采用这种写法,终于又发现了新的写法,代码如下
@download_api.route("/downfile",methods=["GET"])
def down_file():
"""1. 生成表头 2. 生成数据 3. 个性化合并单元格,修改字体属性、修改列宽 3. 返回给前端"""
fp = io.BytesIO() # 生成一个BytesIO对象
book = xlsxwriter.Workbook(fp,{'in_memory':True}) # 可以认为创建了一个Excel文件
worksheet = book.add_worksheet('students_message') # 增加一个sheet
# 1. 生成表头
header_list = ["姓名", "年龄", "年级"]
for col, header in enumerate(header_list):
worksheet.write(0, col, header) # 行(从0开始), 列(从0开始), 内容
# 2. 生成数据
students_data = [("小刚", 12, "7年级")]
for row_number, row_tuple in enumerate(students_data):
for col, per_student_info in enumerate(row_tuple):
worksheet.write(row_number + 1, col, per_student_info) # 遍历导入每个学生的每个信息
book.close()
response = make_response(fp.getvalue())
fp.close()
response.headers['Content-Type'] = "utf-8"
response.headers["Cache-Control"] = "no-cache"
response.headers["Content-Disposition"] = "attachment; filename=download.xlsx"
return response
在这段代码尾部可以看到,获取内存中的值生成了一个响应,然后关闭了内存,这样就不存在因为内存而重复文件的问题了