? 使用 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.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柵欄…