如何在 Flask 中提供靜態文件
P粉754473468
2023-08-23 15:50:41
<p>所以這很尷尬。我在 <code>Flask</code> 中組裝了一個應用程序,目前它只提供一個靜態 HTML 頁面,其中包含一些指向 CSS 和 JS 的連結。我在文檔 <code>Flask</code> 中找不到描述返回靜態文件的位置。是的,我可以使用 <code>render_template</code> 但我知道資料沒有模板化。我認為 <code>send_file</code> 或 <code>url_for</code> 是正確的,但我無法讓它們工作。同時,我打開文件,讀取內容,並使用適當的 mimetype 來設定 <code>Response</code>:</p>
<pre class="brush:php;toolbar:false;">import os.path
from flask import Flask, Response
app = Flask(__name__)
app.config.from_object(__name__)
def root_dir(): # pragma: no cover
return os.path.abspath(os.path.dirname(__file__))
def get_file(filename): # pragma: no cover
try:
src = os.path.join(root_dir(), filename)
# Figure out how flask returns static files
# Tried:
# - render_template
# - send_file
# This should not be so non-obvious
return open(src).read()
except IOError as exc:
return str(exc)
@app.route('/', methods=['GET'])
def metrics(): # pragma: no cover
content = get_file('jenkins_analytics.html')
return Response(content, mimetype="text/html")
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def get_resource(path): # pragma: no cover
mimetypes = {
".css": "text/css",
".html": "text/html",
".js": "application/javascript",
}
complete_path = os.path.join(root_dir(), path)
ext = os.path.splitext(path)[1]
mimetype = mimetypes.get(ext, "text/html")
content = get_file(complete_path)
return Response(content, mimetype=mimetype)
if __name__ == '__main__': # pragma: no cover
app.run(port=80)</pre>
<p>有人想為此提供程式碼範例或網址嗎?我知道這會非常簡單。 </p>
如果您只想移動靜態檔案的位置,那麼最簡單的方法就是在建構函式中宣告路徑。在下面的範例中,我已將範本和靜態檔案移至名為
web
的子資料夾中。static_url_path=''
從 URL 中刪除所有前面的路徑。static_folder='web/static'
提供在資料夾中找到的任何文件web/static
作為靜態檔案。template_folder='web/templates'
類似地,這會更改 模板資料夾。使用此方法,以下 URL 將傳回 CSS 檔案:
最後,這是資料夾結構的快照,其中
flask_server.py
是 Flask 實例:在生產中,在應用程式前面配置 HTTP 伺服器(Nginx、Apache 等),以處理來自靜態資料夾的
/static
請求。專用 Web 伺服器非常擅長有效率地提供靜態文件,儘管在低容量時您可能不會注意到與 Flask 相比的差異。Flask 會自動建立一個
/static/
路由,該路由將為Python 旁的static
資料夾下的任何filename
提供服務定義Flask 應用程式的模組。使用url_for
連結到靜態檔案:url_for('static', filename='js/analytics.js')
您也可以使用
send_from_directory
來提供檔案從您自己的路線中的目錄。這需要一個基本目錄和一個路徑,並確保該路徑包含在該目錄中,這樣可以安全地接受使用者提供的路徑。如果您想在提供文件之前檢查某些內容,例如登入使用者是否具有權限,這可能很有用。請勿將
send_file
或send_static_file
與使用者提供的路徑一起使用。這將使您面臨目錄遍歷攻擊。send_from_directory
旨在安全地處理已知目錄下使用者提供的路徑,如果路徑嘗試轉義該目錄,則會引發錯誤。如果您在記憶體中產生檔案而不將其寫入檔案系統,則可以將
BytesIO
物件傳遞給send_file
將其作為檔案提供。在這種情況下,您需要將其他參數傳遞給send_file
,因為它無法推斷檔案名稱或內容類型等內容。