1. get_valid_filename是什麼?



django.utils.text.get_valid_filename是一個將字符串轉換為文件系統安全文件名的輔助函數。
它會刪除或替換大多數操作系統(如Windows、macOS和Linux)中禁止或有問題的字符(如斜杠、控制字符等),並將字符串標準化為可預測的格式。

為什麼需要它?
當用戶上傳文件或使用隨機輸入(例如博客標題、用戶標籤)生成文件名時,如果包含了如斜杠(../etc/passwd)等目錄遍歷或異常字符,可能會導致文件系統損壞或安全漏洞。


2. 運作方式

from django.utils.text import get_valid_filename

raw = "My: New/Project? 2024*"
safe = get_valid_filename(raw)
print(safe)   # → "My_New_Project_2024"

主要操作

輸入 結果 說明
"my file.txt" "my_file.txt" 空格 → 下劃線
"../etc/passwd" "etc_passwd" 刪除前面的點和斜杠
"file<name>.txt" "file_name_.txt" <>被替換
" " "" 僅有空白時,返回空字符串
"a"*300 "a"*255 裁剪至文件系統限制(255個字符)

該函數是跨平台的,僅允許安全字符集([A-Za-z0-9_.-]),其他字符則替換為下劃線(_)。


3. 有用的情境



情境 必要性
用戶上傳 防止目錄遍歷(../../etc/passwd)和禁止字符
基於slug的文件名 將博客標題轉換為靜態網站用的文件名
數據導出 生成包含數據庫字段(如逗號、引號等)的CSV/JSON文件名
自動備份 從隨機字符串生成包含時間戳的備份文件名

4. 實作示例:圖像上傳保存

# views.py
from django.shortcuts import render
from django.core.files.storage import default_storage
from django.utils.text import get_valid_filename

def upload_image(request):
    if request.method == 'POST':
        uploaded = request.FILES['image']
        # 整理原始文件名
        safe_name = get_valid_filename(uploaded.name)
        # 如有需要,可增加用戶ID或時間戳
        final_name = f"{request.user.id}_{safe_name}"
        path = default_storage.save(f"uploads/{final_name}", uploaded)
        return render(request, 'success.html', {'path': path})
    return render(request, 'upload.html')

結果
無論用戶如何指定文件名,保存的名稱都是安全的,沒有目錄遍歷問題,且重複的可能性也很低。


5. 快速參考

from django.utils.text import get_valid_filename

# 1. 基本整理
safe = get_valid_filename("My: New/Project? 2024*")  # → "My_New_Project_2024"

# 2. 用於文件路徑
path = f"media/{safe}.jpg"

# 3. 結合UUID以確保獨特性
import uuid
unique_name = f"{uuid.uuid4().hex}_{safe}.jpg"

6. 核心整理

  • get_valid_filename能夠用一行代碼保護文件系統免受危險名稱的影響。
  • 每當將用戶輸入隨機字符串轉換為文件名時都應使用。
  • 代碼簡潔,跨平台,且安全性高。

提示: 如果需要保留空格或保留Unicode,可以結合slugify或創建自定義輔助函數,但在大多數情況下,get_valid_filename是最合適的。