当前位置:  首页>> 技术小册>> Flask框架入门指南

实战项目四:实现文件上传与下载功能

在Web开发中,文件上传与下载功能是常见的需求,它们为用户提供了与服务器交互数据的直观方式。本章节将基于Flask框架,详细讲解如何构建一个具备文件上传与下载功能的小型Web应用。我们将通过创建路由、处理表单、保存文件以及提供下载链接等步骤,逐步构建一个实用的功能模块。

1. 项目概述

在本项目中,我们将构建一个简单的Web服务,用户可以通过浏览器上传文件至服务器,并能在之后的某个时间点下载这些文件。为简化示例,我们将专注于文本文件和图片文件的处理,但相同的方法可以轻松地扩展到其他类型的文件。

2. 环境准备

在开始编写代码之前,请确保你已经安装了Python和Flask。你可以通过pip安装Flask(如果尚未安装):

  1. pip install Flask

为了处理文件上传,Flask 自带了 werkzeug.utils.secure_filename 用于安全地处理文件名,避免安全漏洞如路径遍历攻击。此外,我们将使用HTML表单来上传文件,因此无需额外安装库。

3. 创建Flask应用

首先,我们创建一个基本的Flask应用框架。

  1. from flask import Flask, render_template, request, redirect, url_for, send_from_directory
  2. import os
  3. app = Flask(__name__)
  4. # 设置文件上传目录
  5. UPLOAD_FOLDER = 'uploads/'
  6. app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
  7. # 确保上传文件夹存在
  8. if not os.path.exists(UPLOAD_FOLDER):
  9. os.makedirs(UPLOAD_FOLDER)
  10. # 允许的文件类型
  11. ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
  12. def allowed_file(filename):
  13. return '.' in filename and \
  14. filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  15. @app.route('/')
  16. def index():
  17. # 可以在这里列出所有上传的文件供用户下载
  18. files = [f for f in os.listdir(UPLOAD_FOLDER) if os.path.isfile(os.path.join(UPLOAD_FOLDER, f))]
  19. return render_template('index.html', files=files)
  20. # 其他路由和函数将在这里定义
  21. if __name__ == '__main__':
  22. app.run(debug=True)

4. 实现文件上传

接下来,我们实现一个路由来处理文件上传。

  1. @app.route('/upload', methods=['GET', 'POST'])
  2. def upload_file():
  3. if request.method == 'POST':
  4. # 检查是否有文件在请求中
  5. if 'file' not in request.files:
  6. return redirect(request.url)
  7. file = request.files['file']
  8. # 如果用户没有选择文件,浏览器也会提交一个没有文件名的空部分
  9. if file.filename == '':
  10. return redirect(request.url)
  11. if file and allowed_file(file.filename):
  12. filename = secure_filename(file.filename)
  13. file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
  14. return redirect(url_for('index'))
  15. return render_template('upload.html')

注意,这里使用了secure _filename 函数来避免安全问题,并且检查了文件类型是否在允许的列表中。

5. 创建HTML模板

为了上传文件,我们需要一个HTML表单。创建 templates/upload.html

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>Upload File</title>
  5. </head>
  6. <body>
  7. <h1>Upload new File</h1>
  8. <form method=post enctype=multipart/form-data>
  9. <input type=file name=file>
  10. <input type=submit value=Upload>
  11. </form>
  12. </body>
  13. </html>

同时,为了显示上传的文件并提供下载链接,修改 templates/index.html

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>File Manager</title>
  5. </head>
  6. <body>
  7. <h1>Uploaded Files</h1>
  8. <ul>
  9. {% for file in files %}
  10. <li><a href="{{ url_for('download_file', filename=file) }}">{{ file }}</a></li>
  11. {% endfor %}
  12. </ul>
  13. <a href="{{ url_for('upload_file') }}">Upload New File</a>
  14. </body>
  15. </html>

6. 实现文件下载

现在,我们需要一个路由来处理文件下载请求。

  1. @app.route('/download/<filename>')
  2. def download_file(filename):
  3. return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)

这个路由使用 send_from_directory 函数来发送文件作为响应,as_attachment=True 参数确保浏览器以附件形式处理文件,从而触发下载。

7. 测试应用

启动Flask应用后,访问 http://127.0.0.1:5000/ 应该能看到文件列表(初始为空),并提供一个上传新文件的链接。点击链接,上传一个支持的文件类型,然后刷新首页,你应该能看到新上传的文件及其下载链接。

8. 安全性与扩展

  • 安全性:虽然我们已经使用 secure_filename 和检查文件类型来增强安全性,但还需考虑其他潜在的安全风险,如文件大小限制、上传频率控制等。
  • 扩展性:可以添加更多功能,如文件预览、删除已上传文件、文件版本控制等。
  • 用户认证:在实际应用中,你可能需要实现用户认证和授权,以确保只有授权用户才能上传或下载文件。

9. 结论

通过本章节的学习,你应该能够使用Flask框架实现基本的文件上传与下载功能。这不仅是Web开发中的一项基本技能,也是构建更复杂应用的基础。希望你在实践中能够进一步探索和优化这些功能,以满足不同的需求场景。


该分类下的相关小册推荐: