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