如何实现Flask多类型文件下载,摆脱固定Blob类型限制?
多类型文件下载的实现方案
1. 后端代码优化(可选但推荐)
Flask的send_from_directory会自动识别文件MIME类型,我们可以显式指定并优化错误处理,确保返回正确的响应头:
import mimetypes from flask import request, send_from_directory, jsonify @app.route('/api/downloads/', methods=['POST']) def download_file(): uploads = app.config['UPLOAD_FOLDER'] try: response = request.get_json() filename = response["filename"] # 自动推断文件MIME类型 mime_type, _ = mimetypes.guess_type(filename) return send_from_directory( directory=uploads, path=filename, as_attachment=True, mimetype=mime_type # 显式传入确保类型准确 ) except FileNotFoundError: return jsonify({"error": "文件不存在"}), 404 except Exception as e: print(e) return jsonify({"error": "服务器错误"}), 500
2. 前端代码修改
前端需要从后端响应中获取真实的文件类型和文件名,不再固定Blob类型:
async function downloadStuff(filename) { try { // 发送POST请求获取文件 const response = await fetch('/api/downloads/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ filename }) }); if (!response.ok) { throw new Error('文件下载失败'); } // 从响应头获取文件类型 const contentType = response.headers.get('Content-Type') || ''; // 从响应头获取后端指定的下载文件名 const contentDisposition = response.headers.get('Content-Disposition'); let downloadFilename = filename; if (contentDisposition) { const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); if (filenameMatch?.[1]) { downloadFilename = decodeURIComponent(filenameMatch[1].replace(/['"]/g, '')); } } // 直接将响应转为Blob,使用真实的文件类型 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); // 创建下载链接并触发下载 const link = document.createElement('a'); link.href = url; link.download = downloadFilename; // 设置正确的文件名 document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); // 释放URL对象,避免内存泄漏 } catch (error) { console.error('下载错误:', error); alert('文件下载失败,请重试'); } }
核心改进点:
- 移除固定的
application/zip类型,改用后端响应头返回的真实Content-Type - 从
Content-Disposition头提取后端指定的文件名,保证下载文件名与原文件一致 - 使用
response.blob()直接处理响应,简化Blob创建逻辑 - 添加错误处理和内存释放逻辑,提升代码健壮性
内容的提问来源于stack exchange,提问作者JohnDole
相关产品推荐
相关产品推荐

