You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django测试中用openpyxl读取导出文件时出现BadZipFile错误

解决xlwt生成"xlsx"文件导致openpyxl读取BadZipFile错误的问题

问题根源

xlwt是专门生成**旧版Excel格式(.xls)**的库,完全不支持生成基于zip压缩的.xlsx格式。你导出时把文件名后缀设为.xlsx,但文件实际内容仍是二进制的xls格式,而openpyxl仅能读取标准的zip压缩型xlsx文件,这就是触发BadZipFile错误的核心原因。

手动下载后用LibreOffice另存可正常读取,是因为LibreOffice自动识别了文件的真实格式,并将其转换为标准xlsx格式。

解决方案

方案1:替换xlwt为支持xlsx的库(推荐)

使用openpyxl或xlsxwriter直接生成标准xlsx文件,这两个库都支持设置筛选功能,生成的文件能被openpyxl正常读取,单元测试也能顺利进行。

示例代码(xlsxwriter + Django):

from django.http import HttpResponse
import xlsxwriter

def export_filtered_excel(request):
    # 设置对应xlsx格式的响应头
    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = 'attachment; filename="filtered_data.xlsx"'

    # 内存中创建工作簿
    workbook = xlsxwriter.Workbook(response, {'in_memory': True})
    worksheet = workbook.add_worksheet()

    # 写入表头
    worksheet.write('A1', '用户名')
    worksheet.write('B1', '部门')
    worksheet.write('C1', '入职日期')

    # 设置表头行的筛选范围
    worksheet.autofilter('A1:C1')

    # 写入数据示例
    data = [
        ['张三', '技术部', '2023-01-01'],
        ['李四', '市场部', '2023-03-15']
    ]
    for row_idx, row_data in enumerate(data, start=2):
        worksheet.write_row(row_idx, 0, row_data)

    # 关闭工作簿,自动将内容写入response
    workbook.close()

    return response

单元测试代码(openpyxl读取):

from django.test import TestCase
from io import BytesIO
from openpyxl import load_workbook

class ExcelExportTest(TestCase):
    def test_export_and_read(self):
        response = self.client.get('/your-export-api/')
        self.assertEqual(response.status_code, 200)

        # 用BytesIO包装响应内容,读取xlsx文件
        workbook = load_workbook(BytesIO(response.content))
        sheet = workbook.active

        # 验证表头和数据
        self.assertEqual(sheet['A1'].value, '用户名')
        self.assertEqual(sheet['A2'].value, '张三')

方案2:保留xlwt,修正格式匹配

如果必须继续使用xlwt,需要调整格式匹配:

  1. 将文件名后缀改为.xls
  2. 修改响应的Content-Type为application/vnd.ms-excel
  3. 单元测试时使用支持xls格式的库(如xlrd)读取,而非openpyxl

修正后的导出代码:

from django.http import HttpResponse
import xlwt

def export_excel_xls(request):
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = 'attachment; filename="filtered_data.xls"'

    workbook = xlwt.Workbook(encoding='utf-8')
    worksheet = workbook.add_sheet('数据')

    # 写入表头和数据
    worksheet.write(0, 0, '用户名')
    worksheet.write(0, 1, '部门')
    worksheet.write(1, 0, '张三')
    worksheet.write(1, 1, '技术部')

    # 注意:xlwt对xls格式的筛选支持有限,无法像xlsx那样直接设置autofilter,若需完整筛选功能,建议优先用方案1
    workbook.save(response)
    return response

单元测试代码(xlrd读取):

from django.test import TestCase
import xlrd

class XlsExportTest(TestCase):
    def test_export_xls(self):
        response = self.client.get('/your-xls-export-api/')
        self.assertEqual(response.status_code, 200)

        workbook = xlrd.open_workbook(file_contents=response.content)
        sheet = workbook.sheet_by_index(0)
        self.assertEqual(sheet.cell_value(0, 0), '用户名')

总结

核心问题是格式伪装导致不匹配:xlwt生成的xls文件被改成xlsx后缀,让openpyxl误以为是zip压缩格式而报错。优先推荐方案1,换用支持xlsx的库,既能完美实现筛选功能,也能让单元测试流程顺畅。

内容的提问来源于stack exchange,提问作者nitroglycerin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:45:30