掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
File 用于定義客戶端的上傳文件。

說明
因為上傳文件以「表單數(shù)據(jù)」形式發(fā)送。
所以接收上傳文件,要預(yù)先安裝 python-multipart。
例如: pip install python-multipart。
從 fastapi 導(dǎo)入 File 和 UploadFile:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
創(chuàng)建文件(File)參數(shù)的方式與 Body 和 Form 一樣:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
說明
File 是直接繼承自 Form 的類。
注意,從 fastapi 導(dǎo)入的 Query、Path、File 等項,實際上是返回特定類的函數(shù)。
提示
聲明文件體必須使用 File,否則,F(xiàn)astAPI 會把該參數(shù)當(dāng)作查詢參數(shù)或請求體(JSON)參數(shù)。
文件作為「表單數(shù)據(jù)」上傳。
如果把路徑操作函數(shù)參數(shù)的類型聲明為 bytes,F(xiàn)astAPI 將以 bytes 形式讀取和接收文件內(nèi)容。
這種方式把文件的所有內(nèi)容都存儲在內(nèi)存里,適用于小型文件。
不過,很多情況下,UploadFile 更好用。
定義 File 參數(shù)時使用 UploadFile:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
UploadFile 與 bytes 相比有更多優(yōu)勢:
UploadFile 的屬性如下:
UploadFile 支持以下 async 方法,(使用內(nèi)部 SpooledTemporaryFile)可調(diào)用相應(yīng)的文件方法。
因為上述方法都是 async 方法,要搭配「await」使用。
例如,在 async 路徑操作函數(shù) 內(nèi),要用以下方式讀取文件內(nèi)容:
contents = await myfile.read()
在普通 def 路徑操作函數(shù) 內(nèi),則可以直接訪問 UploadFile.file,例如:
contents = myfile.file.read()
async 技術(shù)細節(jié)
使用 async 方法時,F(xiàn)astAPI 在線程池中執(zhí)行文件方法,并 awiat 操作完成。
Starlette 技術(shù)細節(jié)
FastAPI 的 UploadFile 直接繼承自 Starlette 的 UploadFile,但添加了一些必要功能,使之與 Pydantic 及 FastAPI 的其它部件兼容。
與 JSON 不同,HTML 表單(
)向服務(wù)器發(fā)送數(shù)據(jù)通常使用「特殊」的編碼。FastAPI 要確保從正確的位置讀取數(shù)據(jù),而不是讀取 JSON。
技術(shù)細節(jié)
不包含文件時,表單數(shù)據(jù)一般用 application/x-www-form-urlencoded「媒體類型」編碼。
但表單包含文件時,編碼為 multipart/form-data。使用了 File,F(xiàn)astAPI 就知道要從請求體的正確位置獲取文件。
編碼和表單字段詳見 MDN Web 文檔的 POST 小節(jié)。
警告
可在一個路徑操作中聲明多個 File 和 Form 參數(shù),但不能同時聲明要接收 JSON 的 Body 字段。因為此時請求體的編碼是 multipart/form-data,不是 application/json。
這不是 FastAPI 的問題,而是 HTTP 協(xié)議的規(guī)定。
FastAPI 支持同時上傳多個文件。
可用同一個「表單字段」發(fā)送含多個文件的「表單數(shù)據(jù)」。
上傳多個文件時,要聲明含 bytes 或 UploadFile 的列表(List):
from typing import List
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.post("/files/")
async def create_files(files: List[bytes] = File(...)):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async def create_upload_files(files: List[UploadFile] = File(...)):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async def main():
content = """
"""
return HTMLResponse(content=content)
接收的也是含 bytes 或 UploadFile 的列表(list)。
筆記
注意,截至 2019 年 4 月 14 日,Swagger UI 不支持在同一個表單字段中上傳多個文件。詳見 #4276 和 #3641.
不過,F(xiàn)astAPI 已通過 OpenAPI 標(biāo)準(zhǔn)與之兼容。
因此,只要 Swagger UI 或任何其他支持 OpenAPI 的工具支持多文件上傳,都將與 FastAPI 兼容。
技術(shù)細節(jié)
也可以使用 from starlette.responses import HTMLResponse。
fastapi.responses 其實與 starlette.responses 相同,只是為了方便開發(fā)者調(diào)用。實際上,大多數(shù) FastAPI 的響應(yīng)都直接從 Starlette 調(diào)用。
本節(jié)介紹了如何用 File 把上傳文件聲明為(表單數(shù)據(jù)的)輸入?yún)?shù)。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流