当前位置: 首页 > news >正文

✨ 使用 Flask 实现头像文件上传与加载功能

文章目录

      • 🧱 技术栈
      • 🗂️ 项目结构与配置
      • 🔐 用户身份校验逻辑
      • 📤 头像上传接口:`/file/avatar/upload`
      • 📥 加载头像接口:`/file/avatar/load/<filename>`
      • 🧪 示例请求(使用 cURL 测试)
        • 上传头像
        • 加载头像
      • 🔒 安全性与优化建议

在 Web 应用中,文件上传是一个非常常见且不可或缺的需求,尤其是在涉及用户头像、图片展示等功能时。本文将基于 Flask 框架,结合简单的用户身份验证逻辑,实现一个完整的“头像上传与加载”模块。


🧱 技术栈

我们的模块采用了一套简洁而高效的技术栈:

  • 后端框架: Flask
  • 数据库: MySQL(通过自定义的 SQL.DatabasePool 封装类访问)
  • 缓存: Flask-Caching(示例中配置为 simple 缓存)
  • 安全处理: 文件名加密、路径过滤、防止目录遍历攻击

🗂️ 项目结构与配置

首先,我们定义好上传文件的保存路径。这确保了所有头像都存储在一个集中且易于访问的位置:

import osBASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 假设 'apps/fileManage' 是一个子模块,调整 BASE_DIR 到项目根目录
BASE_DIR = BASE_DIR.split(r"\apps\fileManage")[0]
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'uploads')
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

这段代码保证了以下几点:

  • 上传文件将位于项目根目录下的 uploads 文件夹中。
  • 如果 uploads 文件夹不存在,它将自动创建,避免常见的系统错误。

🔐 用户身份校验逻辑

在执行任何文件操作之前,服务器会通过检查传入 Cookie 中的 token 字段来验证用户身份。这一关键步骤确保只有授权用户才能上传或访问文件。

# 假设 'request' 已从 flask 导入
cookie = request.headers.get('Cookie')
# ... 额外解析以从 cookie 字符串中提取 token
token = dict1.get('token') # 假设 dict1 已填充 cookie 键值对
res = sql.executeQuery("SELECT userId FROM onlineUsers JOIN users ON onlineUsers.SessionId = users.userId WHERE onlineUsers.SessionId = '{}'".format(token)
)

如果用户未登录或会话失效,服务器将返回 401 Unauthorized 错误,从而保护您的应用程序免受未经授权的访问。


📤 头像上传接口:/file/avatar/upload

POST 接口负责处理头像图片的上传。完整的流程设计注重鲁棒性和安全性:

  1. 身份验证: 系统首先解析 Cookie 并验证用户会话的合法性。
  2. 文件校验:
    • 它会验证请求中是否存在文件(file 对象)。
    • 文件名不能为空。
    • 至关重要的是,只允许图片文件扩展名(.png.jpg.jpeg.gif),防止上传潜在的恶意文件类型。
  3. 重命名处理: 为了避免命名冲突并确保每个头像都有一个唯一的标识符,文件名会使用 MD5 进行哈希处理,结合用户名和原始文件名生成一个唯一字符串,并附加原始文件扩展名。
  4. 文件保存: 经验证和重命名的文件随后安全地保存到服务器上指定的 uploads 目录中。
  5. 数据库更新: 新上传头像的路径会更新到 users 表中,将头像与相应的用户关联起来。
  6. 返回结果: 成功消息以及可访问的文件路径会返回给客户端。

核心实现代码如下:

# 假设 'request' 已从 flask 导入,并且 'encrypt' 和 'sql' 已定义
file = request.files['file']
# 使用用户名和原始文件名的 MD5 哈希生成唯一文件名
newFilename = encrypt.hash_md5(username + file.filename) + '.' + file.filename.split('.')[-1]
file.save(os.path.join(UPLOAD_FOLDER, newFilename))
# 更新数据库中用户的头像路径
sql.executeUpdate("UPDATE users SET avatar = 'server:{}' WHERE userId = {}".format(newFilename, userId))

📥 加载头像接口:/file/avatar/load/<filename>

GET 接口根据唯一的头像文件名提供已上传的图片资源。它包含了多项安全和性能增强:

  • 路径过滤: 这是一项关键的安全措施,可防止用户在文件名中构造 ../ 序列,从而尝试进行目录遍历攻击并访问 uploads 目录之外的未经授权的文件。
  • 后缀验证: 只允许提供图片文件类型,防止暴露非图片文件。
  • 缓存处理: 该接口支持浏览器缓存,通过减少服务器请求显著提高频繁访问头像的性能。(更多内容请参阅“安全性与优化建议”部分。)
  • MIME 类型推断: 服务器会根据文件扩展名自动推断并设置响应的适当 Content-Type(MIME 类型)(例如,image/pngimage/jpeg),确保浏览器正确渲染图像。
# 假设 'Response' 已从 flask 导入,并且 'data' 包含图像内容
mimetype = f'image/{filename.rsplit(".", 1)[-1].lower()}'
return Response(data, mimetype=mimetype)

🧪 示例请求(使用 cURL 测试)

为了帮助您测试和理解 API 交互,以下是上传和加载头像的 cURL 命令:

上传头像
curl -X POST http://yourdomain.com/file/avatar/upload \-H "Cookie: token=YOUR_TOKEN" \-F "file=@/path/to/your/avatar.png"

请将 YOUR_TOKEN 替换为有效的用户会话令牌,将 /path/to/your/avatar.png 替换为您的图片文件的实际路径。

加载头像
curl http://yourdomain.com/file/avatar/load/xxxxxx.png --output avatar.png

请将 xxxxxx.png 替换为您希望加载的头像的实际唯一文件名。--output avatar.png 标志会将下载的图像保存为 avatar.png 文件。


🔒 安全性与优化建议

虽然我们的模块提供了坚实的基础,但对于生产环境,请考虑以下额外的措施:

  • 文件名哈希: 已实现,这一关键步骤通过确保唯一文件名来防止用户互相覆盖文件。

  • 路径遍历保护: 已实现,这可以防止恶意用户访问指定上传目录之外的文件。

  • 文件大小限制: 实现服务器端检查以限制最大文件大小。这可以防止由于上传过大文件而导致的拒绝服务攻击,并节省服务器资源。

  • 健壮的错误处理: 增强文件操作的错误处理(例如,磁盘已满、权限问题),以便为用户和管理员提供更具信息量的反馈。

  • 云存储集成: 对于生产环境,特别是流量较高的场景,请考虑将头像存储卸载到专门的云存储解决方案,如阿里云 OSS七牛云Amazon S3。这可以显著提高可伸缩性、可靠性,并减轻应用程序服务器的负担。

  • 浏览器缓存以提高性能: 明确地为头像等静态资源向 Response 添加 Cache-Control 头。这允许浏览器缓存图像,从而加快后续加载速度并减少服务器负载。

    return Response(data, mimetype=mimetype, headers={'Cache-Control': 'public, max-age=86400'})
    

    此头信息告诉浏览器将图像缓存 24 小时(86400 秒)。

http://www.lryc.cn/news/599491.html

相关文章:

  • Kafka——多线程开发消费者实例
  • MCP工具开发实战:打造智能体的“超能力“
  • 半相合 - 脐血联合移植
  • C++ 常用的数据结构(适配器容量:栈、队列、优先队列)
  • 海云安斩获“智能金融创新应用“标杆案例 彰显AI安全左移技术创新实力
  • 智能网关芯片:物联网连接的核心引擎
  • VR 污水处理技术赋能广州猎德污水处理厂,处理效率显著提升
  • FastDFS如何提供HTTP访问电子影像文件
  • 网络协议,DHCP 协议等。
  • 每日面试题14:CMS与G1垃圾回收器的区别
  • http-proxy-middleware MaxListenersExceededWarning
  • Java 大视界 -- 基于 Java 的大数据分布式存储在工业互联网数据管理与边缘计算协同中的创新实践(364)
  • 零碳园区如何破局?安科瑞EMS3.0以智慧能源管理重构低碳未来
  • 借助Aspose.HTML控件,在 Python 中将 SVG 转换为 PDF
  • Kimi K2 大语言模型技术特性与应用实践分析
  • 酷暑来袭,科技如何让城市清凉又洁净?
  • 冠捷科技 | 内生外化,精准触达,实现数字化转型精准赋能
  • Pytorch混合精度训练最佳实践
  • 人工智能冗余:大语言模型为何有时表现不佳(以及我们能做些什么)
  • 广东省省考备考——常识:科技常识(持续更新)
  • 【指南版】网络与信息安全岗位系列(一):网络安全工程师
  • DNF: Decouple and Feedback Network for Seeing in the Dark
  • 深入解析MongoDB分片原理与运维实践指南
  • OpenCV 图像变换全解析:从镜像翻转到仿射变换的实践指南
  • docker搭建ray集群
  • NodeJS搭建SSE接口服务
  • 【C#补全计划:类和对象(七)—— 重写虚方法】
  • 重构 MVC:让经典架构完美适配复杂智能系统的后端业务逻辑层(内附框架示例代码)
  • 图片查重从设计到实现(4)图片向量化存储-Milvus 单机版部署
  • 【大模型实战】提示工程(Prompt Engineering)