Flask 實現文件上傳及文件訪問
文件上傳功能在很多網站上面都有,比如智聯、拉鉤、Boss 等各大招聘網站,你可以在這些網站上面上傳你的簡歷文件并快速的發送給各個公司的 HR,可以說是非常方便了。那么這節課我們就來使用 Flask 框架實現一個文件上傳的功能,并且上傳之后能正常訪問到這個文件。
1. 程序功能和結構
1.1 程序功能
用戶通過瀏覽器進行上傳文件和下載文件,界面如下所示:
用戶選擇文件,點擊上傳文件按鈕后,開始上傳文件。上傳文件成功過后,上傳的文件會出現在下載文件清單中,點擊文件名即可下載文件。
1.2 程序結構
例子包括 5 個源文件,如下表所示:
程序 | 說明 |
---|---|
app.py | Flask 后端程序,實現文件上傳 |
templates/index.html | 上傳和下載文件的頁面模板 |
templates/upload.html | 上傳成功后的頁面模板 |
upload/ | 用于存放已經上傳的文件的目錄 |
upload/a.txt | 已經上傳的文件,用于測試 |
upload/b.txt | 已經上傳的文件,用于測試 |
1.3 源程序下載
2. 后端程序 app.py
2.1 引入相關庫
#!/usr/bin/python3
from flask import Flask, render_template, request, send_from_directory
import os
app = Flask(__name__)
從 flask 模塊中引入 request 對象,request 對象中的屬性 files 記錄了上傳文件的相關信息;從 flask 模塊中引入函數 send_from_directory,該函數用于實現下載文件。
2.2 設置 / 路由
@app.route('/')
def index():
entries = os.listdir('./upload')
return render_template('index.html', entries = entries)
設置訪問路徑 / 時,使用函數 index 進行處理,函數 index 列出目錄 upload 下所有的文件名,作為參數傳給首頁的模板 index.html。在首頁 index.html 中根據 entries 顯示每個文件的下載鏈接。
2.3 設置 /upload 路由
@app.route('/upload', methods=['POST'])
def upload():
f = request.files['file']
path = os.path.join('./upload', f.filename)
f.save(path)
return render_template('upload.html')
設置訪問路徑 /upload 時,使用函數 upload 進行處理。函數 upload 從 request 對象中獲取上傳的文件信息,request.files 是一個字典,使用表單中的文件字段名作為索引。
在第 5 行,方法 f.save 將文件保存到指定路徑 path 中。如果上傳的文件名是 test.txt,則 path 為 ./upload/test.txt。
在第 6 行,在服務端保存上傳文件后,渲染頁面模板 upload.html,通知用戶已經上傳成功。
2.4 設置 /files 路由
@app.route('/files/<filename>')
def files(filename):
return send_from_directory('./upload', filename, as_attachment=True)
app.run(debug = True)
每個文件都有一個下載鏈接,形式為 /files/ 文件名,假如文件名為 test.txt,則下載鏈接為 /files/test.txt。
設置訪問路徑 /files/<filename> 時,使用函數 files 進行處理,其中 <filename> 表示訪問路徑 URL 中文件的名稱,它作為參數傳遞給函數 files。函數 files 調用 send_from_directory 將 upload 目錄下的文件發送給客戶,as_attachment=True 表示文件作為附件下載。
3. 頁面模板 upload.html
<html>
<head>
<meta charset="UTF-8">
<title>文件上傳</title>
</head>
<body>
<h1>上傳成功</h1>
<a href='/'>返回主頁</a>
</body>
</html>
在服務端保存上傳文件后,服務端返回頁面模板 upload.html,通知已經上傳成功。用戶點擊 "返回主頁",可以返回到網站根頁面,在根頁面可以查看到所有已經上傳的文件,并下載。
4. 頁面模板 index.html
訪問路徑 / 時,顯示 index.html,包括兩部分內容:
- 上傳文件表單
- 下載文件清單
4.1 上傳文件
<html>
<head>
<meta charset="UTF-8">
<title>文件上傳</title>
</head>
<body>
<h2>上傳文件</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" class="input">
<input type="submit" value="上傳" class="input button">
</form>
定義上傳文件表單 form,使用 POST 方法提交給服務端 /upload 頁面處理,屬性 enctype=“multipart/form-data” 表示表單中包含有上傳文件的數據需要處理。
4.2 下載文件
<h2>下載文件</h2>
<ol>
{% for entry in entries %}
<li><a href='/files/{{entry}}'>{{entry}}</a>
{% endfor %}
</ol>
</body>
</html>
在 2.2 小節,訪問路徑 / 時,處理函數 index 列出目錄 upload 下所有的文件名,作為參數傳給首頁的模板 index.html。假設當前 upload 目錄下存在 3 個文件: a.txt、b.txt、c.txt,則 entries 為 [‘a.txt’, ‘b.txt’, ‘c.txt’],頁面模板被渲染為:
<h2>下載文件</h2>
<ol>
<li><a href='/files/a.txt'>a.txt</a>
<li><a href='/files/b.txt'>b.txt</a>
<li><a href='/files/c.txt'>c.txt</a>
</ol>
用戶點擊文件名鏈接后,即可下載相應的文件。
5. 小結
本小節講解了如何上傳和下載文件,使用思維導圖概括如下: