在Django、DRF中通过POST请求生成CSV并返回流式响应的正确方法
通过POST请求实现Django流式CSV下载的正确方法
你的代码无法返回文件响应,主要有三个问题:Content-Disposition头格式错误、CSV内容生成不规范、DRF渲染器干扰。以下是修正方案:
关键问题分析
- Content-Disposition头转义错误:原代码用
"包裹文件名,这是HTML转义字符,HTTP响应头中直接使用双引号即可,否则浏览器无法识别附件类型。 - CSV内容生成不规范:手动拼接行无法处理字段含逗号、引号等特殊字符的情况,容易导致CSV格式损坏。
- DRF渲染器干扰:
api_view默认使用JSON渲染器,可能会修改流式响应的头信息或内容。
修正后的完整代码
方案一:使用csv模块生成规范流式内容+自定义CSV渲染器
import csv from io import StringIO from django.http import StreamingHttpResponse from rest_framework.decorators import api_view, renderer_classes from rest_framework.renderers import BaseRenderer # 自定义CSV渲染器,让DRF正确识别响应类型 class CSVRenderer(BaseRenderer): media_type = 'text/csv' format = 'csv' def generate_csv_data(): # 用csv.writer处理特殊字符,生成标准CSV output = StringIO() writer = csv.writer(output) # 写入表头和数据 writer.writerow(['Name', 'Email']) writer.writerow(['John Doe', 'john.doe@example.com']) writer.writerow(['Jane Smith', 'jane.smith@example.com']) # 分块读取并返回,实现流式输出 output.seek(0) while True: chunk = output.read(1024) if not chunk: break yield chunk @api_view(['POST']) @renderer_classes([CSVRenderer]) def download_csv(request): response = StreamingHttpResponse(generate_csv_data(), content_type='text/csv') # 正确设置下载头,无需转义引号 response['Content-Disposition'] = 'attachment; filename="data.csv"' return response
方案二:绕过DRF渲染器,直接返回原生响应
如果不需要自定义渲染器,也可以手动禁用DRF的渲染流程:
import csv from io import StringIO from django.http import StreamingHttpResponse from rest_framework.decorators import api_view def generate_csv_data(): output = StringIO() writer = csv.writer(output) writer.writerow(['Name', 'Email']) writer.writerow(['John Doe', 'john.doe@example.com']) writer.writerow(['Jane Smith', 'jane.smith@example.com']) output.seek(0) return output.read() @api_view(['POST']) def download_csv(request): response = StreamingHttpResponse(generate_csv_data(), content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="data.csv"' # 告诉DRF不要修改该响应 response.accepted_renderer = None response.accepted_media_type = 'text/csv' response.renderer_context = {} return response
核心要点总结
- 始终使用
csv模块生成CSV内容,避免手动拼接导致的格式错误。 - Content-Disposition头直接用
attachment; filename="文件名.csv"格式,无需HTML转义。 - 若使用DRF的
api_view,需指定CSV渲染器或手动禁用DRF的渲染干扰,确保响应被浏览器识别为下载文件。
内容的提问来源于stack exchange,提问作者Digvijaysing Rajput
相关产品推荐
相关产品推荐

