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

在这段代码尾部可以看到,获取内存中的值生成了一个响应,然后关闭了内存,这样就不存在因为内存而重复文件的问题了

原文地址:https://www.cnblogs.com/wuren-best/p/14379395.html