使用Python Flask建置影像圖檔上傳網站服務(二)

延續上一篇文章,本文將介紹HTML表單的上傳檔案欄位的參數以及接收和儲存上傳檔的基本Python Flask程式。

上傳檔案的HTML表單網頁

底下是上傳檔案的表單外觀和HTML碼,<input type=”file”;>標籤元素會在Chrome瀏覽器上呈現「選擇檔案」鈕,此欄位的名稱可自行設定,這個例子將它命名成”filename”。

上傳表單

<form>標籤的enctype屬性的兩個常用值如下:

  • application/x-www-form-urlencoded:用於傳送不含檔案資料的文字表單。此為預設值,所以enctype=”application/x-www-form-urlencoded”可省略不寫。
  • multipart/form-data:用於傳送包含「檔案」欄位的表單資料。multipart代表「多個部份」,也就是上傳檔案將被自動分割成數個、分批上傳。

從HTML表單的「檔案」欄位篩選上傳檔案類型

定義「檔案」欄位的 <input type=”file”> 標籤,除了設定欄位名稱的name屬性,還有下列常用的屬性:

  • required:代表此欄位是「必填」。
  • multiple:代表這個欄位可接收多個檔案,設定範例:
<input type="file"  name="filename" multiple>
  • accept:設定允許上傳的檔案類型。底下的設定僅允許上傳.doc和.docx檔,副檔名之間用逗號隔開
<input type="file"  name="filename" accept=".doc, .docx">

底下的設定僅允許上傳.png, .jpg和.gif圖檔

<input type="file"  name="filename" accept=".png, .jpg, .gif">

另一種寫法是透過MIME類型篩選上傳檔案格式(參閱第11章),底下的檔案欄位僅允許上傳影像圖檔

<input type="file"  name="filename" accept="image/*">

影像、視訊以及聲音的MIME類型設置如下:

  • 代表任意影像檔:”image/*”
  • 代表任意視訊檔:”video/*”
  • 代表任意聲音檔:”audio/*”

副檔名和MIME可合併使用,底下的檔案欄位僅接受上傳影像以及Word文件

<input type="file"  name="filename" accept="image/*, .doc, .docx ">

包含一個「檔案」欄位的表單的完整網頁(Flask網頁樣版)HTML碼如下,此檔案欄位是必填、僅接受影像圖檔

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="{{ url_for('static',  filename='favicon.ico') }}">
    <title>上傳影像檔</title>
  </head>

  <body>
  <h1>上傳影像檔</h1>
  <form method="POST" enctype="multipart/form-data"  action="{{ url_for('upload_file') }}">
    <input type="file" name="filename"  accept="image/*" required>
    <input type="submit" value="上傳">
  </form>
  </body>
</html>

筆者把處理表單的Python函式命名成upload_file(),所以表單的action屬性設成”{{ url_for(‘upload_file’) }}”。

建立Python Flask網站服務的虛擬環境

下文將透過Python Flask程式接收上傳檔案,為了方便管理專案程式,請先建立Python虛擬環境。筆者在D磁碟機根目錄新增一個photoshare資料夾,然後執行左下的命令建立虛擬環境,接著新增src和templates,以及static,  uploads等資料夾,相關說明請參閱《超圖解Python程式設計入門》第10章「佈署網站到雲端空間」。

Python Flask網站服務的虛擬環境

取得「上傳資料夾」的絕對路徑

此範例的Python程式將把上傳檔存入static/uploads路徑。上傳檔的儲存路徑必須是「絕對路徑」,Python 3的pathlib「路徑程式庫」裡的Path()函式可傳回檔案的絕對路徑。

底下是在虛擬環境的src資料夾中的app.py檔,執行Path()函式所傳回的絕對路徑:

取得「上傳資料夾」的絕對路徑

假設你的Python虛擬環境設置在macOS或Linux系統的使用者家目錄,執行結果將類似這樣:

取得「上傳資料夾」的絕對路徑

底下的程式片段將把src/static/uploads的絕對路徑(此例為:”D:\photoshare\src\static\uploads”)存入UPLOAD_FOLDER變數:

import os
import pathlib

# 取得目前檔案所在的資料夾 
SRC_PATH =  pathlib.Path(__file__).parent.absolute()
# 結合目前的檔案路徑和static及uploads路徑 
UPLOAD_FOLDER = os.path.join(SRC_PATH,  'static', 'uploads')

基本的Python Flask檔案上傳處理程式

底下是接收、儲存上傳檔的Python Flask程式,筆者將它命名成app.py,存入虛擬環境的src資料夾:

import os
import pathlib
from flask import Flask, url_for, redirect,  render_template, request

# 取得目前檔案所在的資料夾 
SRC_PATH =  pathlib.Path(__file__).parent.absolute()
UPLOAD_FOLDER = os.path.join(SRC_PATH,  'static', 'uploads')

app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/', methods=['POST'])
def upload_file():
    file = request.files['filename']
    if file.filename != '':
        file.save(os.path.join(UPLOAD_FOLDER, file.filename))
    return redirect(url_for('index'))

if __name__ == "__main__":
    app.run()

執行此Python程式後,透過瀏覽器開啟本機網站(127.0.0.1:5000),底下的路由敘述將被執行,傳送index.html網頁給瀏覽器:

路由敘述

當使用者按下表單的「上傳」鈕,底下的路由敘述將被執行,接收上傳的檔案並存入src/static/uploads路徑,然後把瀏覽器重新導向到首頁。

儲存上傳檔的路由敘述

以上是個簡單的Python Flask上傳檔案服務,它有兩個缺點:

  • 雖然HTML表單已設置僅限上傳圖檔,但使用者仍舊可以選取任意檔案並且上傳。
  • 上傳檔案之後,沒有顯示任何訊息就跳回首頁。

下一篇文章將解決這兩個問題。

Posts created 483

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top