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是最合適的。
目前沒有評論。