FastAPI(24)- 詳解 File,上傳檔案
阿新 • • 發佈:2022-01-05
FastAPI(24)- 詳解 File,上傳檔案
前言
可以使用 FastAPI 提供的 File 定義客戶端要上傳的檔案
學習 File 前最好先學習 Form:https://www.cnblogs.com/poloyy/p/15311533.html
安裝 python-multipart
要用 File,需要先安裝這個庫
pip install python-multipart
FIle
File 是繼承 Form,所以可以定義和 Form 相同的元資料以及額外的驗證
上傳單個檔案的栗子
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠蘿測試筆記
# blog: https://www.cnblogs.com/poloyy/
# time: 2021/9/22 9:52 上午
# file: 21_File.py
"""
import uvicorn
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
# file 引數型別是位元組 bytes
@app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len (file)}
# file 引數型別是 UploadFile
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
result = {
"filename": file.filename,
"content-type": file.content_type,
"read": await file.read()
}
return result
if __name__ == "__main__":
uvicorn.run(app="21_File:app" , host="127.0.0.1", port=8080, reload=True, debug=True)
重點
- 因為 UploadFile 物件提供的方法都是 async 非同步的,所以呼叫的時候都要加 await 比如await file.read()(後面會詳解 async/await )
- 當使用非同步方法時,FastAPI 線上程池中執行檔案方法並等待它們
不加 await 呼叫 async 方法會報錯
raise ValueError(errors)
ValueError: [TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
WARNING: StatReload detected file change in '21_File.py'. Reloading...
file: bytes 的請求結果
file: UploadFile 的請求結果
檢視 Swagger API 文件
這樣就可以直接在 Swagger API 文件上測試上傳檔案功能啦
file: bytes
- FastAPI 將會讀取檔案,接收到的內容就是檔案位元組
- 會將整個內容儲存在記憶體中,更適用於小檔案
file: UploadFile
FastAPI 的 UploadFile 直接繼承了 Starlette 的 UploadFile,但增加了一些必要的部分,使其與 Pydantic 和 FastAPI 的其他部分相容
UploadFile 相比 bytes 的優勢
- 儲存在記憶體中的檔案達到最大大小限制,超過此限制後,它將儲存在磁碟中,可以很好地處理大檔案,如影象、視訊、大型二進位制檔案等,而不會消耗所有記憶體
- 可以從上傳的檔案中獲取元資料
- 有一個類似檔案的 async 非同步介面
- 它公開了一個 Python SpooledTemporaryFile 物件,可以將它傳遞給其他需要檔案的庫
UploadFile 具有以下屬性
- filename:str,
上傳的原始檔名,例如
myimage.jpg - content_type:str,包含 content-type(MIME type / media type),例如image/jpeg
- file:一個 SpooledTemporaryFile(一個類似檔案的物件)。 這是實際的 Python 檔案,可以將其直接傳遞給其他需要“類檔案”物件的函式或庫
UploadFIle 具有以下 async 非同步方法
- write(data):寫入data ( str或 bytes ) 到檔案
- read(size):讀取檔案的 size (int) 個位元組/字元
- seek(offset):轉到檔案中的位元組位置 offset(int),如:await myfile.seek(0)將轉到檔案的開頭
- close():關閉檔案
上傳多個檔案的栗子
from typing import List
@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]}