在Web开发中,文件上传与下载功能是常见的需求,它们为用户提供了与服务器交互数据的直观方式。本章节将基于Flask框架,详细讲解如何构建一个具备文件上传与下载功能的小型Web应用。我们将通过创建路由、处理表单、保存文件以及提供下载链接等步骤,逐步构建一个实用的功能模块。
在本项目中,我们将构建一个简单的Web服务,用户可以通过浏览器上传文件至服务器,并能在之后的某个时间点下载这些文件。为简化示例,我们将专注于文本文件和图片文件的处理,但相同的方法可以轻松地扩展到其他类型的文件。
在开始编写代码之前,请确保你已经安装了Python和Flask。你可以通过pip安装Flask(如果尚未安装):
pip install Flask
为了处理文件上传,Flask 自带了 werkzeug.utils.secure_filename
用于安全地处理文件名,避免安全漏洞如路径遍历攻击。此外,我们将使用HTML表单来上传文件,因此无需额外安装库。
首先,我们创建一个基本的Flask应用框架。
from flask import Flask, render_template, request, redirect, url_for, send_from_directory
import os
app = Flask(__name__)
# 设置文件上传目录
UPLOAD_FOLDER = 'uploads/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# 确保上传文件夹存在
if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER)
# 允许的文件类型
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def index():
# 可以在这里列出所有上传的文件供用户下载
files = [f for f in os.listdir(UPLOAD_FOLDER) if os.path.isfile(os.path.join(UPLOAD_FOLDER, f))]
return render_template('index.html', files=files)
# 其他路由和函数将在这里定义
if __name__ == '__main__':
app.run(debug=True)
接下来,我们实现一个路由来处理文件上传。
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# 检查是否有文件在请求中
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
# 如果用户没有选择文件,浏览器也会提交一个没有文件名的空部分
if file.filename == '':
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('index'))
return render_template('upload.html')
注意,这里使用了secure _filename
函数来避免安全问题,并且检查了文件类型是否在允许的列表中。
为了上传文件,我们需要一个HTML表单。创建 templates/upload.html
:
<!doctype html>
<html>
<head>
<title>Upload File</title>
</head>
<body>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
</body>
</html>
同时,为了显示上传的文件并提供下载链接,修改 templates/index.html
:
<!doctype html>
<html>
<head>
<title>File Manager</title>
</head>
<body>
<h1>Uploaded Files</h1>
<ul>
{% for file in files %}
<li><a href="{{ url_for('download_file', filename=file) }}">{{ file }}</a></li>
{% endfor %}
</ul>
<a href="{{ url_for('upload_file') }}">Upload New File</a>
</body>
</html>
现在,我们需要一个路由来处理文件下载请求。
@app.route('/download/<filename>')
def download_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
这个路由使用 send_from_directory
函数来发送文件作为响应,as_attachment=True
参数确保浏览器以附件形式处理文件,从而触发下载。
启动Flask应用后,访问 http://127.0.0.1:5000/
应该能看到文件列表(初始为空),并提供一个上传新文件的链接。点击链接,上传一个支持的文件类型,然后刷新首页,你应该能看到新上传的文件及其下载链接。
secure_filename
和检查文件类型来增强安全性,但还需考虑其他潜在的安全风险,如文件大小限制、上传频率控制等。通过本章节的学习,你应该能够使用Flask框架实现基本的文件上传与下载功能。这不仅是Web开发中的一项基本技能,也是构建更复杂应用的基础。希望你在实践中能够进一步探索和优化这些功能,以满足不同的需求场景。