小明:你好,小李,我最近在做一个研究生信息管理系统,需要实现一个文件下载的功能。你有没有什么建议?
小李:你好,小明。下载功能其实挺常见的,但要确保安全性和效率。你用的是什么技术栈?
小明:我们用的是Python和Flask框架,数据库是MySQL。现在需要让管理员可以下载学生的成绩文件或者论文附件。
小李:那你可以考虑使用Flask的路由来处理下载请求。首先,你需要在数据库里存储文件的路径或ID,然后在前端提供一个下载链接。
小明:具体怎么操作呢?比如,用户点击下载按钮后,系统怎么获取文件并返回给用户?
小李:好的,我们可以用Flask的`send_file`函数。它可以直接将文件发送给客户端。不过要注意文件路径是否正确,以及权限问题。
小明:那我可以写一个路由,比如`/download/
小李:对的,这样结构清晰。不过还要注意安全性,比如防止SQL注入,确保用户只能访问自己有权限的文件。

小明:明白了。那代码部分该怎么写呢?能给我一个示例吗?
小李:当然可以。下面是一个简单的例子,假设你有一个名为`files`的表,里面包含`id`和`file_path`字段。
from flask import Flask, send_file, request
import mysql.connector
app = Flask(__name__)
# 数据库连接配置
db_config = {
'host': 'localhost',
'user': 'root',
'password': 'your_password',
'database': 'student_db'
}
@app.route('/download/', methods=['GET'])
def download_file(file_id):
# 连接数据库
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor()
# 查询文件路径
query = "SELECT file_path FROM files WHERE id = %s"
cursor.execute(query, (file_id,))
result = cursor.fetchone()
if not result:
return "文件不存在", 404
file_path = result[0]
# 返回文件
return send_file(file_path, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
小明:这个例子看起来不错,但我担心如果文件路径不正确会出错,怎么办?
小李:你可以加一些异常处理。比如,在读取文件前检查文件是否存在,或者捕获可能的错误。
小明:那应该怎么修改代码呢?

小李:可以添加try-except块,同时在`send_file`时设置合适的MIME类型,避免浏览器无法识别。
from flask import Flask, send_file, request
import mysql.connector
import os
app = Flask(__name__)
db_config = {
'host': 'localhost',
'user': 'root',
'password': 'your_password',
'database': 'student_db'
}
@app.route('/download/', methods=['GET'])
def download_file(file_id):
try:
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor()
query = "SELECT file_path FROM files WHERE id = %s"
cursor.execute(query, (file_id,))
result = cursor.fetchone()
if not result:
return "文件不存在", 404
file_path = result[0]
# 检查文件是否存在
if not os.path.exists(file_path):
return "文件损坏或已删除", 404
# 获取文件名
filename = os.path.basename(file_path)
# 设置MIME类型(可选)
# 例如:'application/pdf' 或 'text/plain'
# 也可以通过文件扩展名自动判断
return send_file(file_path, as_attachment=True, download_name=filename)
except Exception as e:
return f"下载失败: {str(e)}", 500
finally:
if 'conn' in locals():
conn.close()
if __name__ == '__main__':
app.run(debug=True)
小明:这样就更健壮了。那前端怎么调用这个下载接口呢?
小李:前端可以通过AJAX请求或者直接跳转到该URL。如果是表单提交,可以用`下载`。
小明:明白了。那如果有大量文件下载,会不会影响性能?

小李:确实,频繁下载大文件可能会占用服务器资源。你可以考虑使用缓存、异步任务(如Celery)或者CDN来优化。
小明:那如果用户没有权限下载某个文件怎么办?
小李:你需要在查询文件时验证用户的权限。比如,可以在数据库中添加一个`user_id`字段,表示哪个用户上传了文件,然后在下载时检查当前用户是否有权限。
小明:那是不是还需要一个用户认证系统?
小李:是的。你可以使用Flask-Login或者JWT进行用户认证,确保只有合法用户才能访问特定文件。
小明:听起来很复杂,但这是必须的。那有没有其他优化建议?
小李:可以考虑使用分页、限制下载频率、记录下载日志等。此外,还可以对文件进行压缩或加密,提高安全性。
小明:非常感谢你的帮助,我现在对下载功能有了更深入的理解。
小李:不客气,如果你还有其他问题,随时来找我!
