Flask文件下载send_file中文文件名处理解决方案
- Flask文件下载中文文件名处理解决方案
- 问题背景
- 问题分析
- 核心问题
- 常见症状
- 解决方案
- 技术实现
- 关键技术点
- 完整实现示例
Flask文件下载中文文件名处理解决方案
问题背景
在Web应用开发中,当用户下载包含中文字符的文件时,经常会遇到文件名乱码或无法正确显示的问题。这是由于HTTP协议中的 Content-Disposition 头部字段对非ASCII字符的处理限制导致的。
问题分析
核心问题
- 编码问题 :HTTP头部字段默认使用ASCII编码,无法直接支持中文等Unicode字符
- 浏览器兼容性 :不同浏览器对非ASCII文件名的处理方式不同
- RFC标准 :需要遵循RFC 6266标准来正确处理国际化文件名
常见症状
- 下载的文件名显示为乱码
- 中文文件名变成问号或其他符号
- 部分浏览器无法正确解析文件名
解决方案
技术实现
在Flask应用中,我们采用了双重编码策略来确保中文文件名的正确处理:
from urllib.parse import quote
from flask import send_file# 设置文件名,支持中文文件名
file_name = quote(download_name)
response.headers['Content-Disposition'] = f'attachment; filename="{file_name}"; filename*=utf-8\'\'\'{file_name}'
关键技术点
- URL编码处理
file_name = quote(download_name)
- 使用 urllib.parse.quote() 对文件名进行URL编码
- 将中文字符转换为百分号编码格式(如: %E4%B8%AD%E6%96%87 )
- 双重文件名策略
response.headers['Content-Disposition'] = f'attachment; filename="{file_name}";
filename*=utf-8\'\'\'{file_name}'
参数说明:
- filename=“{file_name}” :为旧版浏览器提供ASCII兼容的文件名
- filename*=utf-8’‘’{file_name} :符合RFC 6266标准的国际化文件名 3. RFC 6266标准格式
filename*=charset'language'encoded-filename
- charset :字符集(utf-8)
- language :语言标识(空字符串表示未指定)
- encoded-filename :URL编码后的文件名
完整实现示例
class TaskDownloadAPI(Resource):def get(self, task_id):"""下载翻译后的文件"""try:# ... 其他业务逻辑 ...# 获取原始文件名download_name = task_info.get('original_filename')if not download_name:file_ext = os.path.splitext(output_file)[1]download_name = f"translated_{task_id}{file_ext}"# 创建响应response = send_file(output_file,as_attachment=True)# 设置文件名,支持中文文件名file_name = quote(download_name)response.headers['Content-Disposition'] = f'attachment; filename="{file_name}"; filename*=utf-8\'\'\'{file_name}'return responseexcept Exception as e:logger.error(f"文件下载异常 - 任务ID: {task_id}, 错误: {str(e)}")return {'error': f'下载文件时发生错误: {str(e)}'}, 500