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

Django下载xls文件打开损坏、FileResponse传参报错问题求助

Django xls文件下载功能异常修复方案

问题概述

开发环境基于Python+Django,xls文件下载逻辑写在views.py中,业务要求必须使用xls格式(需配套后续导入功能,不可替换为xlsx),两次代码实现均出现异常:

  • 第一版代码可触发下载,但下载后的xls文件打开提示损坏
  • 第二版改用FileResponse实现后,访问路由直接报500错误,提示HTTP status code must be an integer

根因分析

第一版代码问题

第一版实现代码如下:

def downloadfile(request, filename=''):
  if filename != '':
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    filename = 'SampleExcel.xls'
    filepath = BASE_DIR + "\SampleExcel\SampleExcel.xls"
    path = open(filepath, encoding='cp437')
    mime_type, _ = mimetypes.guess_type(filepath)
    response = HttpResponse(path, content_type=mime_type)
    response['Content-Disposition'] = "attachment; filename=%s" % filename
    return response
  else:
    return HttpResponseRedirect("adduser", {})

核心问题:xls是二进制格式文件,必须以二进制模式读取。上述代码打开文件时未指定'rb'模式,默认以文本模式打开,还指定了cp437编码,读取过程中会对二进制字节做编码转义处理,直接篡改了原文件的二进制内容,最终下载的文件结构损坏无法打开。
另外手动拼接路径写死\分隔符,在Linux部署环境下会出现路径找不到的问题。

第二版代码问题

第二版调整后的代码如下:

if filename != '':
  BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  filename = 'SampleExcel.xls'
  filepath = BASE_DIR + "\SampleExcel\SampleExcel.xls" 
  return FileResponse(open(filepath, 'rb') , True, filename)
else:
  return HttpResponseRedirect("adduser", {})

核心问题:FileResponse参数传递顺序错误。FileResponse第二个位置参数是HTTP状态码status,要求传入整数类型,代码中第二个位置传了布尔值True,第三个位置直接传文件名,不符合参数定义,导致响应初始化失败,最终触发响应写入时的字节类型断言错误,对应错误日志:

Traceback (most recent call last): 
File "C:\Users\PCSI\AppData\Local\Programs\Python\Python310\lib\wsgiref\handlers.py", line 138, in run self.finish_response() 
File "C:\Users\PCSI\AppData\Local\Programs\Python\Python310\lib\wsgiref\handlers.py", line 184, in finish_response self.write(data) 
File "C:\Users\PCSI\AppData\Local\Programs\Python\Python310\lib\wsgiref\handlers.py", line 279, in write assert type(data) is bytes, \ 
AssertionError: write() argument must be a bytes instance 
[27/Jun/2022 15:07:10] "GET /downloadfile/SampleExcel.xls HTTP/1.1" 500 59

正确实现代码

修复所有问题后的可运行代码如下:

import os
from django.http import FileResponse, HttpResponseRedirect
from django.urls import reverse
import mimetypes

def downloadfile(request, filename=''):
    if filename:
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        # 用os.path.join拼接路径,自动适配不同操作系统的路径分隔符
        filepath = os.path.join(BASE_DIR, "SampleExcel", "SampleExcel.xls")
        # 二进制只读模式打开文件,禁止指定文本编码参数,避免文件内容被转义
        file = open(filepath, 'rb')
        mime_type, _ = mimetypes.guess_type(filepath)
        # 以关键字参数形式传参,避免位置参数顺序错误
        response = FileResponse(
            file,
            as_attachment=True,
            filename=filename,
            content_type=mime_type
        )
        return response
    else:
        # 用reverse解析路由别名,避免硬编码路由路径
        return HttpResponseRedirect(reverse("adduser"))

注意事项

  • 所有二进制格式文件(xls、图片、压缩包等)下载时,都必须以'rb'二进制只读模式打开,不能用文本模式,也不要给open()传encoding参数,否则会导致文件损坏
  • 调用Django内置响应类时,不确定参数顺序尽量用关键字参数传递,避免位置传参错位引发的异常
  • 服务器上部署时要保证Django进程对目标xls文件有读权限,否则会触发权限报错
  • 路径拼接统一用os.path.join,不要手动写/或\分隔符,避免跨系统部署时路径不兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:18:17