文章目录

      • 🧱 技术栈
      • 🗂️ 项目结构与配置
      • 🔐 用户身份校验逻辑
      • 📤 头像上传接口:`/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.pswp.cn/bicheng/90974.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90974.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90974.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

去除视频字幕 5: 使用 ProPainter, 记录探索过程

使用 ProPainter 去除视频上的字幕&#xff0c;效果演示&#xff08;比之前好多了。&#xff09;。 1. 项目目标 去除视频 (bear.webm) 中的硬字幕。 2. 初始尝试与关键失败&#xff1a;IOPaint 方法: 使用 IOPaint&#xff08;一个图像修复工具&#xff09;配合 PaddleOCR 逐…

JavaScript HTTP 请求:从老古董到新潮流

前端开发离不开跟后端打交道&#xff0c;HTTP 请求就是这座桥梁。JavaScript 提供了好几种方式来发请求&#xff0c;从老牌的 XMLHttpRequest (XHR) 到现代的 Fetch API&#xff0c;再到各种好用的第三方库&#xff08;像 Axios、Ky、Superagent&#xff09;。咱们一个一个聊清…

Windows10系统使用Cmake4.1.0构建工具+Visual Studio2022编译Opencv4.11教程

安装提示 后续安装本Cmake和Opencv版本及以上都可以。Microsoft Visual Studio2022已默认安装&#xff0c;没有安装给出教程链接。 一、Cmake4.1.0下载 1.官网下载&#xff1a;https://cmake.org/download/&#xff0c;找到cmake-4.1.0-rc3-windows-x86_64.zip版本 2.压缩包…

【性能测试】Jmeter+Grafana+InfluxDB+Prometheus Windows安装部署教程

一、工具作用与整体架构 1.1 各工具核心作用 工具作用描述关键特性Jmeter性能测试工具&#xff0c;模拟多用户并发请求&#xff0c;生成测试数据支持HTTP/HTTPS、数据库等多种协议&#xff0c;可自定义测试场景InfluxDB时序数据库&#xff0c;专门存储时间序列数据&#xff0…

【Kubernetes】使用Deployment进行的资源调度,资源清理,伸缩与更新管控

Kubernetes Deployment 实战&#xff1a;从资源清理到伸缩与更新管控 一、基础准备&#xff1a;清理闲置 ReplicaSet 在使用 Deployment 时&#xff0c;每次更新都会生成新的 ReplicaSet&#xff08;简称 RS&#xff09;&#xff0c;旧的 RS 会被保留但设置为 DESIRED0。这些闲…

stm32使用USB虚拟串口,因电脑缺少官方驱动而识别失败(全系列32单片机可用)

驱动下载地址 官网地址&#xff1a;https://www.st.com/en/development-tools/stsw-stm32102.html

枚举中间位置基础篇

参考资料来源灵神在力扣所发的题单&#xff0c;仅供分享学习笔记和记录&#xff0c;无商业用途。 核心思路&#xff1a; 一&#xff1a;直接直接用数据结构记录需要的数据&#xff0c;在枚举右&#xff0c;维护左的循环中&#xff0c;删除当前位置的元素即可达成一样效果 二…

企业选择将服务器放在IDC机房托管的优势

在服务器作为数据存储和传输的核心设备的社会环境中&#xff0c;服务器的稳定性和安全性会直接影响到企业业务的连续性和用户的满意程度&#xff0c;随着云计算技术和大数据的兴起&#xff0c;企业对于服务器的需求也在日益增加&#xff0c;而如何高效、安全的管理服务器则是各…

自动化UI测试工具TestComplete的AI双引擎:即时数据集 + 自愈测试

随着敏捷开发和持续交付模式的普及&#xff0c;传统的软件测试方法正面临着前所未有的挑战。测试团队在追求快速迭代的同时&#xff0c;往往陷入测试数据准备和测试维护的泥潭&#xff0c;严重制约了交付效率和质量保障能力。 TestComplete作为业界领先的自动化测试工具&#…

用KNN实现手写数字识别:基于 OpenCV 和 scikit-learn 的实战教学 (超级超级超级简单)

用KNN实现手写数字识别&#xff1a;基于 OpenCV 和 scikit-learn 的实战教学在这篇文章中&#xff0c;我们将使用 KNN&#xff08;K-Nearest Neighbors&#xff09;算法对手写数字进行分类识别。我们会用 OpenCV 读取图像并预处理数据&#xff0c;用 scikit-learn 构建并训练模…

数据结构自学Day15 -- 非比较排序--计数排序

一、计数排序&#xff08;Counting Sort&#xff09;计数排序是一种非比较型的排序算法&#xff0c;它的核心思想是&#xff1a;利用“元素的值”来确定它在结果数组中的位置&#xff0c;通过“统计每个数出现的次数”来完成排序。二、如何实现计数排序&#xff08;核心步骤&am…

k8s的权限

来自博客&#xff1a;25-k8s集群中-RBAC用户角色资源权限_权限 资源 角色-CSDN博客 一.RBAC概述&#xff08;基于角色的访问控制&#xff09; 1.图解 用户&#xff1a; 1.user 2.serviceAccount 3.Group 用户角色 1.Role:局部资源角色 2.clusterRole:全局资源角色额 角色绑…

C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(三)

目录 队列数据管理 代码实现 测试代码 绑定信息(交换机-队列)管理 代码实现 测试代码 队列数据管理 当前队列数据的管理&#xff0c;本质上是队列描述信息的管理&#xff0c;描述当前服务器上有哪些队列。 定义队列描述数据类 队列名称是否持久化标志是否独占标志是否自…

51c自动驾驶~合集9

自己的原文哦~ https://blog.51cto.com/whaosoft/11627386 #端到端1 说起端到端&#xff0c;每个从业者可能都觉得会是下一代自动驾驶量产方案绕不开的点&#xff01;特斯拉率先吹响了方案更新的号角&#xff0c;无论是完全端到端&#xff0c;还是专注于planner的模…

时间长了忘记jupyter的环境是哪个了

有这些但是忘记是哪个了jupyter kernelspec list查看内核路径&#xff0c;这个内核是用来告诉jupyter 去哪找内核配置的到这个路径下打开json文件查看使用的python环境从而确定是哪个conda环境为jupyter使用的python环境jupyter的工作原理&#xff1a;在创建conda环境后会安装j…

PYTHON从入门到实践-15数据可视化

数据可视化是数据分析中不可或缺的一环&#xff0c;它能够将抽象的数据转化为直观的图形&#xff0c;帮助我们更好地理解数据特征和发现潜在规律。本文将介绍如何使用Python中的Matplotlib和Plotly库进行数据可视化&#xff0c;并通过掷骰子的概率模拟案例展示可视化的实际应用…

Spring IOC 容器 **默认注册 Bean** 的 8 条规则

Spring IOC 容器 默认注册 Bean 的 8 条规则 &#xff08;Spring Framework 6.x 源码级总结&#xff09;阅读提示&#xff1a;把下面 8 条规则背下来&#xff0c;再读 Spring 源码时&#xff0c;你会在任何一行代码里立刻知道「这个 BeanDefinition 是从哪儿来的」。1️⃣ 环境…

29.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--用户配置服务

用户配置服务是孢子记账中最简单的部分。简单说&#xff0c;用户配置服务就是用户自定义的配置项存储服务&#xff0c;用于我们的APP根据用户的配置实现指定的功能。它提供了一个简单的接口&#xff0c;允许用户存储和检索他们的配置数据。就目前来说&#xff0c;用户配置只有一…

Python实现PDF按页分割:灵活拆分文档的技术指南

Python实现PDF按页分割&#xff1a;灵活拆分文档的技术指南 PDF文件处理是日常工作中的常见需求&#xff0c;特别是当我们需要将大型PDF文档拆分为多个部分时。本文将介绍如何使用Python创建一个灵活的PDF分割工具&#xff0c;能够根据用户指定的页数范围任意分割文档。 需求分…

「iOS」——GCD其他方法详解

GCD学习GCD其他方法dispatch_semaphore &#xff08;信号量&#xff09;**什么是信号量**dispatch_semaphore主要作用dispatch_semaphore主要作用异步转同步设置一个最大开辟的线程数加锁机制dispatch_time_t 两种形式GCD一次性代码(只执行一次)dispatch_barrier_async/sync栅栏…