Avastage FastAPI võimsus tõhusaks failide üleslaadimiseks mitmeosaliste vormide kaudu. See põhjalik juhend käsitleb parimaid praktikaid, veahaldust ja täiustatud tehnikaid globaalsetele arendajatele.
FastAPI failide üleslaadimise meisterlikkus: sügav sukeldumine mitmeosaliste vormide töötlemisse
Tänapäevastes veebirakendustes on failide üleslaadimise haldamise võimekus põhinõue. Olgu tegemist kasutajate profiilipiltide esitamise, dokumentide töötlemise või meedia jagamisega, on vastupidavad ja tõhusad failide üleslaadimise mehhanismid üliolulised. FastAPI, kõrge jõudlusega Pythoni veebiraamistik, on selles valdkonnas suurepärane, pakkudes sujuvaid viise mitmeosaliste vormiandmete haldamiseks, mis on standard failide saatmiseks üle HTTP. See põhjalik juhend juhatab teid läbi FastAPI failide üleslaadimise peensuste, alates põhirakendusest kuni täiustatud kaalutlusteni, tagades, et saate enesekindlalt luua võimsaid ja skaleeritavaid API-sid globaalsele publikule.
Mitmeosaliste vormiandmete mõistmine
Enne FastAPI rakendusse süvenemist on oluline mõista, mis on mitmeosaline vormiandmestik. Kui veebibrauser esitab faile sisaldava vormi, kasutab see tavaliselt atribuuti enctype="multipart/form-data". See kodeeringutüüp jaotab vormi esitamise mitmeks osaks, millest igaühel on oma sisutüüp ja paigutuse teave. See võimaldab ühe HTTP-päringu raames edastada erinevat tüüpi andmeid, sealhulgas tekstivälju, mittetekstivälju ja binaarfaile.
Iga osa mitmeosalises päringus koosneb:
- Content-Disposition päis: Määrab vormivälja nime (
name) ja failide puhul algse failinime (filename). - Content-Type päis: Näitab osa MIME tüüpi (nt
text/plain,image/jpeg). - Sisu: Selle osa tegelikud andmed.
FastAPI lähenemine failide üleslaadimisele
FastAPI kasutab Pythoni standardteeki ja integreerub sujuvalt Pydanticuga andmete valideerimiseks. Failide üleslaadimiseks kasutab see fastapi moodulist pärinevat UploadFile tüüpi. See klass pakub mugavat ja turvalist liidest üleslaaditud failiandmetele juurdepääsuks.
Põhiline faili üleslaadimise rakendamine
Alustame lihtsa näitega, kuidas luua FastAPI-s lõpp-punkt, mis aktsepteerib ühe faili üleslaadimist. Kasutame failiparameetri deklareerimiseks fastapi-st pärinevat funktsiooni File.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: UploadFile):
return {"filename": file.filename, "content_type": file.content_type}
Selles näites:
- Impordime
FastAPI,FilejaUploadFile. - Lõpp-punkt
/files/on defineeritud kuiPOSTpäring. - Parameeter
fileon annotatsioonigaUploadFile, mis tähendab, et see ootab faili üleslaadimist. - Lõpp-punkti funktsiooni sees saame juurdepääsu üleslaaditud faili omadustele nagu
filenamejacontent_type.
Kui klient saadab POST-päringu aadressile /files/ koos lisatud failiga (tavaliselt vormi kaudu, millel on enctype="multipart/form-data"), tegeleb FastAPI automaatselt parsimisega ja pakub UploadFile objekti. Seejärel saate selle objektiga suhelda.
Üleslaaditud failide salvestamine
Tihti peate üleslaaditud faili kettale salvestama või selle sisu töötlema. UploadFile objekt pakub selleks meetodeid:
read(): Loeb kogu faili sisu baitidena mällu. Kasutage seda väiksemate failide puhul.write(content: bytes): Kirjutab baidid faili.seek(offset: int): Muudab faili hetkepositsiooni.close(): Sulgeb faili.
On oluline käsitleda failitoiminguid asünkroonselt, eriti suurte failide või I/O-ga seotud ülesannete puhul. FastAPI UploadFile toetab asünkroonseid operatsioone.
from fastapi import FastAPI, File, UploadFile
import shutil
app = FastAPI()
@app.post("/files/save/")
async def save_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"file '{file.filename}' saved at '{file_location}'"}
Selles täiustatud näites:
- Kasutame
File(...), et näidata, et see parameeter on nõutav. - Määrame kohaliku tee, kuhu fail salvestatakse. Veenduge, et
uploadskaust on olemas. - Avame sihtfaili binaarses kirjutamisrežiimis (`"wb+"`).
- Loeme asünkroonselt üleslaaditud faili sisu, kasutades
await file.read(), ja seejärel kirjutame selle kohalikku faili.
Märkus: Kogu faili mällu lugemine käsuga await file.read() võib väga suurte failide puhul olla problemaatiline. Sellistel juhtudel kaaluge faili sisu voogedastamist.
Faili sisu voogedastus
Suurte failide puhul võib kogu sisu mällu lugemine põhjustada liigset mälukasutust ja potentsiaalseid mälupuuduse vigu. Mälu säästvam lähenemine on faili voogedastus tükkhaaval. Funktsioon shutil.copyfileobj on selleks suurepärane, kuid me peame seda kohandama asünkroonsete operatsioonide jaoks.
from fastapi import FastAPI, File, UploadFile
import aiofiles # Install using: pip install aiofiles
app = FastAPI()
@app.post("/files/stream/")
async def stream_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
async with aiofiles.open(file_location, "wb") as out_file:
content = await file.read()
await out_file.write(content)
return {"info": f"file '{file.filename}' streamed and saved at '{file_location}'"}
aiofiles abil saame tõhusalt voogedastada üleslaaditud faili sisu sihtfaili, ilma et laadiksime kogu faili korraga mällu. await file.read() loeb selles kontekstis ikkagi kogu faili, kuid aiofiles tegeleb kirjutamisega tõhusamalt. Tõelise tükkhaaval voogedastuse jaoks UploadFile'iga tuleks tavaliselt itereerida üle await file.read(chunk_size), kuid aiofiles.open ja await out_file.write(content) on levinud ja jõudluselt hea muster salvestamiseks.
Selgesõnalisem voogedastuse lähenemine tükeldamist kasutades:
from fastapi import FastAPI, File, UploadFile
import aiofiles
app = FastAPI()
CHUNK_SIZE = 1024 * 1024 # 1MB chunk size
@app.post("/files/chunked_stream/")
async def chunked_stream_file(file: UploadFile = File(...)):
file_location = f"./uploads/{file.filename}"
async with aiofiles.open(file_location, "wb") as out_file:
while content := await file.read(CHUNK_SIZE):
await out_file.write(content)
return {"info": f"file '{file.filename}' chunked streamed and saved at '{file_location}'"}
See chunked_stream_file lõpp-punkt loeb faili 1 MB suuruste tükkidena ja kirjutab iga tüki väljundfaili. See on kõige mälusäästlikum viis potentsiaalselt väga suurte failide käsitlemiseks.
Mitme faili üleslaadimise käsitlemine
Veebirakendused nõuavad sageli kasutajatelt mitme faili samaaegset üleslaadimist. FastAPI muudab selle lihtsaks.
Failide nimekirja üleslaadimine
Saate aktsepteerida failide nimekirja, annotades oma parameetri UploadFile'i nimekirjaga.
from fastapi import FastAPI, File, UploadFile, Form
from typing import List
app = FastAPI()
@app.post("/files/multiple/")
async def create_multiple_files(
files: List[UploadFile] = File(...)
):
results = []
for file in files:
# Process each file, e.g., save it
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
results.append({"filename": file.filename, "content_type": file.content_type, "saved_at": file_location})
return {"files_processed": results}
Selle stsenaariumi puhul peab klient saatma mitu osa sama vormivälja nimega (nt `files`). FastAPI kogub need Pythoni UploadFile objektide nimekirja.
Failide ja muude vormiandmete segamine
On tavaline, et vormid sisaldavad nii failivälju kui ka tavalisi tekstivälju. FastAPI käsitleb seda, lubades teil deklareerida teisi parameetreid standardsete tüübiannotatsioonide abil koos Form'iga vormiväljade jaoks, mis ei ole failid.
from fastapi import FastAPI, File, UploadFile, Form
from typing import List
app = FastAPI()
@app.post("/files/mixed/")
async def upload_mixed_data(
description: str = Form(...),
files: List[UploadFile] = File(...) # Accepts multiple files with the name 'files'
):
results = []
for file in files:
# Process each file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
results.append({"filename": file.filename, "content_type": file.content_type, "saved_at": file_location})
return {
"description": description,
"files_processed": results
}
Kasutades tööriistu nagu Swagger UI või Postman, määrate description tavalise vormiväljana ja lisate seejärel mitu osa files välja jaoks, millest igaühe sisutüüp on vastav pildi/dokumendi tüüp.
Täiustatud funktsioonid ja parimad praktikad
Lisaks põhilisele failikäsitlusele on vastupidavate failide üleslaadimise API-de loomiseks üliolulised mitmed täiustatud funktsioonid ja parimad praktikad.
Faili suuruse piirangud
Piiramatute failide üleslaadimise lubamine võib põhjustada teenusetõkestamise rünnakuid või liigset ressursikasutust. Kuigi FastAPI ise ei kehtesta raamistiku tasandil vaikimisi rangeid piiranguid, peaksite rakendama kontrolle:
- Rakenduse tasandil: Kontrollige faili suurust pärast selle kättesaamist, kuid enne töötlemist või salvestamist.
- Veebiserveri/puhverserveri tasandil: Konfigureerige oma veebiserver (nt Nginx, Uvicorn töötajatega) teatud andmemahu ületavate päringute tagasilükkamiseks.
Näide rakendustasandi suuruse kontrollist:
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()
MAX_FILE_SIZE_MB = 10
MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024
@app.post("/files/limited_size/")
async def upload_with_size_limit(file: UploadFile = File(...)):
if len(await file.read()) > MAX_FILE_SIZE_BYTES:
raise HTTPException(status_code=400, detail=f"File is too large. Maximum size is {MAX_FILE_SIZE_MB}MB.")
# Reset file pointer to read content again
await file.seek(0)
# Proceed with saving or processing the file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"File '{file.filename}' uploaded successfully."}
Oluline: Pärast faili lugemist selle suuruse kontrollimiseks peate kasutama await file.seek(0), et lähtestada failikursor algusesse, kui kavatsete selle sisu uuesti lugeda (nt selle salvestamiseks).
Lubatud failitüübid (MIME tüübid)
Üleslaadimiste piiramine konkreetsete failitüüpidega suurendab turvalisust ja tagab andmete terviklikkuse. Saate kontrollida UploadFile objekti content_type atribuuti.
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()
ALLOWED_FILE_TYPES = {"image/jpeg", "image/png", "application/pdf"}
@app.post("/files/restricted_types/")
async def upload_restricted_types(file: UploadFile = File(...)):
if file.content_type not in ALLOWED_FILE_TYPES:
raise HTTPException(status_code=400, detail=f"Unsupported file type: {file.content_type}. Allowed types are: {', '.join(ALLOWED_FILE_TYPES)}")
# Proceed with saving or processing the file
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"File '{file.filename}' uploaded successfully and is of an allowed type."}
Tugevamaks tüübikontrolliks, eriti piltide puhul, võiksite kaaluda teekide nagu Pillow kasutamist faili tegeliku sisu kontrollimiseks, kuna MIME tüüpe saab mõnikord võltsida.
Veahaldus ja kasutajate tagasiside
Andke kasutajale selgeid ja tegevusele suunatud veateateid. Kasutage standardsete HTTP veavastuste jaoks FastAPI HTTPException'i.
- Faili ei leitud/puudub: Kui nõutavat failiparameetrit ei saadeta.
- Faili suurus ületatud: Nagu on näidatud suuruse piirangu näites.
- Kehtetu failitüüp: Nagu on näidatud tüübi piirangu näites.
- Serveri vead: Probleemide korral faili salvestamise või töötlemise ajal (nt ketas täis, õiguste vead).
Turvakaalutlused
Failide üleslaadimine tekitab turvariske:
- Pahatahtlikud failid: Käivitatavate failide (
.exe,.sh) või teisteks failitüüpideks maskeeritud skriptide üleslaadimine. Valideerige alati failitüüpe ja kaaluge üleslaaditud failide pahavara suhtes skannimist. - Kataloogist läbimurdmine (Path Traversal): Puhastage failinimed, et takistada ründajatel failide üleslaadimist ettenähtud kaustadesse (nt kasutades failinimesid nagu
../../etc/passwd). FastAPIUploadFiletegeleb põhilise failinime puhastamisega, kuid lisahoolikus on mõistlik. - Teenusetõkestamine: Rakendage faili suuruse piiranguid ja potentsiaalselt kiirusepiiranguid üleslaadimise lõpp-punktides.
- Saidideülene skriptimine (XSS): Kui kuvate failinimesid või faili sisu otse veebilehel, veenduge, et need on korralikult kaitstud, et vältida XSS-rünnakuid.
Parim praktika: Salvestage üleslaaditud failid väljaspool oma veebiserveri dokumendijuurt ja serveerige neid spetsiaalse lõpp-punkti kaudu sobivate juurdepääsukontrollidega või kasutage sisuedastusvõrku (CDN).
Pydantic mudelite kasutamine failide üleslaadimisel
Kuigi UploadFile on failide peamine tüüp, saate failide üleslaadimise integreerida Pydanticu mudelitesse keerukamate andmestruktuuride jaoks. Kuid otsesed failide üleslaadimise väljad standardsetes Pydanticu mudelites ei ole mitmeosaliste vormide jaoks loomulikult toetatud. Selle asemel saate tavaliselt faili eraldi parameetrina ja seejärel töötlete selle potentsiaalselt vormingusse, mida saab salvestada või valideerida Pydanticu mudeliga.
Levinud muster on metaandmete jaoks Pydanticu mudel ja seejärel faili eraldi vastuvõtmine:
from fastapi import FastAPI, File, UploadFile, Form
from pydantic import BaseModel
from typing import Optional
class UploadMetadata(BaseModel):
title: str
description: Optional[str] = None
app = FastAPI()
@app.post("/files/model_metadata/")
async def upload_with_metadata(
metadata: str = Form(...), # Receive metadata as a JSON string
file: UploadFile = File(...)
):
import json
try:
metadata_obj = UploadMetadata(**json.loads(metadata))
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format for metadata")
except Exception as e:
raise HTTPException(status_code=400, detail=f"Error parsing metadata: {e}")
# Now you have metadata_obj and file
# Proceed with saving file and using metadata
file_location = f"./uploads/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {
"message": "File uploaded successfully with metadata",
"metadata": metadata_obj,
"filename": file.filename
}
Selles mustris saadab klient metaandmed JSON-stringina vormiväljal (nt metadata) ja faili eraldi mitmeosalise osana. Seejärel parsib server JSON-stringi Pydanticu objektiks.
Suurte failide üleslaadimine ja tükeldamine
Väga suurte failide (nt gigabaitide) puhul võib isegi voogedastus põrkuda veebiserveri või kliendipoolsete piirangute vastu. Täiustatum tehnika on tükeldatud üleslaadimine, kus klient jaotab faili väiksemateks osadeks ja laadib need üles järjestikku või paralleelselt. Seejärel paneb server need tükid uuesti kokku. See nõuab tavaliselt kohandatud kliendipoolset loogikat ja serveri lõpp-punkti, mis on loodud tükkide haldamiseks (nt tükkide tuvastamine, ajutine salvestamine ja lõplik kokkupanek).
Kuigi FastAPI ei paku sisseehitatud tuge kliendi algatatud tükeldatud üleslaadimiste jaoks, saate selle loogika oma FastAPI lõpp-punktides rakendada. See hõlmab lõpp-punktide loomist, mis:
- Võtavad vastu üksikuid failitükke.
- Salvestavad need tükid ajutiselt, võimalusel koos metaandmetega, mis näitavad nende järjekorda ja tükkide koguarvu.
- Pakuvad lõpp-punkti või mehhanismi, mis annab märku, kui kõik tükid on üles laaditud, käivitades kokkupanemisprotsessi.
See on keerulisem ettevõtmine ja hõlmab sageli JavaScripti teeke kliendi poolel.
Rahvusvahelistumise ja globaliseerumise kaalutlused
Globaalsele publikule API-de loomisel nõuavad failide üleslaadimised erilist tähelepanu:
- Failinimed: Kasutajad üle maailma võivad failinimedes kasutada mitte-ASCII märke (nt aktsendid, ideogrammid). Veenduge, et teie süsteem käsitleb ja salvestab neid failinimesid korrektselt. UTF-8 kodeering on üldiselt standardne, kuid sügav ühilduvus võib nõuda hoolikat kodeerimist/dekodeerimist ja puhastamist.
- Faili suuruse ühikud: Kuigi MB ja GB on levinud, olge teadlik sellest, kuidas kasutajad failide suurusi tajuvad. Piirangute kuvamine kasutajasõbralikul viisil on oluline.
- Sisutüübid: Kasutajad võivad üles laadida faile vähem levinud MIME tüüpidega. Veenduge, et teie lubatud tüüpide loend on teie kasutusjuhtumi jaoks piisavalt põhjalik või paindlik.
- Piirkondlikud regulatsioonid: Olge teadlik andmete asukohaseadustest ja regulatsioonidest erinevates riikides. Üleslaaditud failide salvestamine võib nõuda nende reeglite järgimist.
- Kasutajaliides: Failide üleslaadimise kliendipoolne liides peaks olema intuitiivne ning toetama kasutaja keelt ja lokaati.
Tööriistad ja teegid testimiseks
Failide üleslaadimise lõpp-punktide testimine on ülioluline. Siin on mõned levinud tööriistad:
- Swagger UI (Interaktiivne API dokumentatsioon): FastAPI genereerib automaatselt Swagger UI dokumentatsiooni. Saate failide üleslaadimisi testida otse brauseri liidesest. Otsige faili sisestusvälja ja klõpsake nuppu "Vali fail".
- Postman: Populaarne API arendus- ja testimisvahend. Faili üleslaadimise päringu saatmiseks:
- Määrake päringu meetodiks POST.
- Sisestage oma API lõpp-punkti URL.
- Minge vahekaardile "Body".
- Valige tüübiks "form-data".
- Võtme-väärtuse paarides sisestage oma failiparameetri nimi (nt
file). - Muutke tüüp "Text" asemel "File".
- Klõpsake "Choose Files", et valida fail oma kohalikust süsteemist.
- Kui teil on muid vormivälju, lisage need sarnaselt, hoides nende tüübiks "Text".
- Saatke päring.
- cURL: Käsurea tööriist HTTP-päringute tegemiseks.
- Ühe faili jaoks:
curl -X POST -F "file=@/path/to/your/local/file.txt" http://localhost:8000/files/ - Mitme faili jaoks:
curl -X POST -F "files=@/path/to/file1.txt" -F "files=@/path/to/file2.png" http://localhost:8000/files/multiple/ - Segatud andmete jaoks:
curl -X POST -F "description=My description" -F "files=@/path/to/file.txt" http://localhost:8000/files/mixed/ - Pythoni
requeststeek: Programmiliseks testimiseks.
import requests
url = "http://localhost:8000/files/save/"
files = {'file': open('/path/to/your/local/file.txt', 'rb')}
response = requests.post(url, files=files)
print(response.json())
# For multiple files
url_multiple = "http://localhost:8000/files/multiple/"
files_multiple = {
'files': [('file1.txt', open('/path/to/file1.txt', 'rb')),
('image.png', open('/path/to/image.png', 'rb'))]
}
response_multiple = requests.post(url_multiple, files=files_multiple)
print(response_multiple.json())
# For mixed data
url_mixed = "http://localhost:8000/files/mixed/"
data = {'description': 'Test description'}
files_mixed = {'files': open('/path/to/another_file.txt', 'rb')}
response_mixed = requests.post(url_mixed, data=data, files=files_mixed)
print(response_mixed.json())
Kokkuvõte
FastAPI pakub võimsat, tõhusat ja intuitiivset viisi mitmeosaliste failide üleslaadimiste käsitlemiseks. Kasutades UploadFile tüüpi ja asünkroonset programmeerimist, saavad arendajad luua vastupidavaid API-sid, mis integreerivad sujuvalt failikäsitlusvõimalusi. Pidage meeles, et prioriteediks on turvalisus, rakendage asjakohast veahaldust ja arvestage globaalse kasutajaskonna vajadustega, käsitledes selliseid aspekte nagu failinimede kodeerimine ja regulatiivne vastavus.
Ükskõik, kas ehitate lihtsat piltide jagamise teenust või keerulist dokumenditöötlusplatvormi, on FastAPI failide üleslaadimise funktsioonide valdamine märkimisväärne eelis. Jätkake selle võimekuste uurimist, rakendage parimaid praktikaid ja pakkuge oma rahvusvahelisele publikule erakordseid kasutajakogemusi.