Flask Web 開發這本書基本上做完了,後面還需要溫習,但是自己做的博客總覺得簡陋了點,所以,在動腦子開發新功能
今天想到最基本的功能,自定義頭像
那這樣的功能,設計到2大基本功能塊
1:如何進行文件的上傳和保存
2:如何在用戶模型裏面將頭像照片和用戶掛鉤起來
第二個問題我在查閱了網上的討論後,得出基本上2種方法,
第一種是將圖片變成二進制以後存入數據庫
第二種是將圖片直接存放於文件系統中
先研究如何上傳文件成功這個事情
從最簡單的開始
在main的views文件內,添加以下準備工作
import os
from flask import Flask, request, redirect, url_for
UPLOAD_FOLDER=r'E:\flasky\app\upload'
設置UPLOAD_FOLDER的路徑,表示文件最終要存在哪一個位置
@main.route('/upload_file',methods = ['GET','POST'])
def upload_file():
#...
if request.method == 'POST':
file = request.files['file']
file.save(os.path.join(UPLOAD_FOLDER,file.filename))
return '<p>success</p>'
return '''
<!DOCTYPE html>
<title>Change new icon</title>
<h1>Upload new </h1>
<form action = "" method = "post" enctype=multipart/form-data>
<input type = "file" name = file>
<input type = "submit" value = Upload>
</form>
'''
file=request.files['file']表示,從request請求的files字典中,取出file對應的文件。這個文件是一個FileStorage對象,這個我們後面再講
這個文件對象擁有一個函數功能來保存文件,叫做save()
這個文件對象還擁有一個屬性來提取文件名,叫做filename
他的參數就是路徑名稱
如上面代碼,我用了os.path.join拼接的方法來做出保存路徑名
至於提交保存以後的返回頁面,我先簡單做了一個 顯示 success的頁面表示功能成功
而整個頁面的渲染,直接在return裏面寫入了這個表單,我們來看看功能
PS: 在用戶資料頁面,我已經加入了按鈕來通向更改頭像的頁面,這個就不多說了
好,最重要的一環節上傳文件已經完成了,接下來的工作就是對代碼的完善了
比如,添加指定允許文件類型的範圍
ALLOWED_EXTENSIONS=set(['txt','pdf','png','jpg','jpeg','gif'])
於是乎,代碼變成了
UPLOAD_FOLDER=r'E:\flasky\app\upload'
ALLOWED_EXTENSIONS=set(['txt','pdf','png','jpg','jpeg','gif'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS
@main.route('/upload_file',methods = ['GET','POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
file.save(os.path.join(UPLOAD_FOLDER,file.filename))
return '<p>success</p>'
return '<p> 你上傳了不允許的文件類型 </p>'
return '''
<!DOCTYPE html>
<title>Change new icon</title>
<h1>Upload new </h1>
<form action = "" method = "post" enctype=multipart/form-data>
<input type = "file" name = file>
<input type = "submit" value = Upload>
</form>
'''
好,講到這裏,就要回過頭來看看Flask官方文檔的說明了
首先第一點,request的files屬性
也就是說,files是一個MultiDict的形式,而裏面的每個文件,都是一個FileStorage對象
那我們再來看下FileStorage的說明
所以說,非常方便,可以通過file.filename ,直接獲取文件的名字
另外,這個文件對象,可以直接用save功能儲存,2可以有2個參數,一個是dst表示存放路徑,第二個是緩存尺寸,表示在存儲過程中的大小,默認16kb。
我們來看下效果,我們用MP3後綴名的文件來進行測試
我在檢測到是不允許的文件類型時,返回寫了一句提示
接着,我們要再講一個功能 secure_filename(),他是防止用於起一些可以影響到系統運行的文件名,來擾亂你的網站
比如如官方文檔所說的
再來看下這個函數的功能,其實他爲了保證文件名不會影響到系統,他就把文件名裏面的斜槓和空格,替換成了下劃線
這樣,就保證了文件只會在當前目錄使用,而不會由於路徑問題被利用去做其他事情。
所以,在儲存文件之前,通過這個函數把文件名先修改一下
@main.route('/upload_file',methods = ['GET','POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(UPLOAD_FOLDER,filename))
return '<p>success</p>'
return '<p> 你上傳了不允許的文件類型 </p>'
return '''
<!DOCTYPE html>
<title>Change new icon</title>
<h1>Upload new </h1>
<form action = "" method = "post" enctype=multipart/form-data>
<input type = "file" name = file>
<input type = "submit" value = Upload>
</form>
'''
最後,還有一個功能,就是立即查看已經剛剛上傳的文件
我這裏創建了一個jpg圖像文件
這裏需要用到的函數是send_from_directory
我們將上傳的代碼再次修改一下,變成上傳完以後立刻預覽
UPLOAD_FOLDER=r'E:\flasky\app\upload'
ALLOWED_EXTENSIONS=set(['txt','pdf','png','jpg','jpeg','gif'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS
@main.route('/upload_file',methods = ['GET','POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(UPLOAD_FOLDER,filename))
return redirect(url_for('.uploaded_file',filename=filename)) #跳轉到預覽頁面
return '<p> 你上傳了不允許的文件類型 </p>'
return '''
<!DOCTYPE html>
<title>Change new icon</title>
<h1>Upload new </h1>
<form action = "" method = "post" enctype=multipart/form-data>
<input type = "file" name = file>
<input type = "submit" value = Upload>
</form>
'''
@main.route('/uploaded_file/<filename>')
def uploaded_file(filename):
return send_from_directory(UPLOAD_FOLDER,filename)
我創建了一張t.jpg的圖片,裏面用文本框寫了一句話,也就是下面預覽裏面看到的
到這裏爲止,基本的上傳和預覽功能就實現了,後面還要再和用戶頭像掛鉤,還得再動動腦子。