Envoyer des fichiers¶
🌐 Traduction par IA et humains
Cette traduction a été réalisée par une IA guidée par des humains. 🤝
Elle peut contenir des erreurs d'interprétation du sens original, ou paraître peu naturelle, etc. 🤖
Vous pouvez améliorer cette traduction en nous aidant à mieux guider le LLM d'IA.
Vous pouvez définir des fichiers à téléverser par le client en utilisant File.
Info
Pour recevoir des fichiers téléversés, installez d'abord python-multipart.
Assurez-vous de créer un environnement virtuel, de l'activer, puis d'installer le paquet, par exemple :
$ pip install python-multipart
C'est parce que les fichiers téléversés sont envoyés en « données de formulaire ».
Importer File¶
Importez File et UploadFile depuis fastapi :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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):
return {"filename": file.filename}
Définir des paramètres File¶
Créez des paramètres de fichier de la même manière que pour Body ou Form :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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):
return {"filename": file.filename}
Info
File est une classe qui hérite directement de Form.
Mais souvenez-vous que lorsque vous importez Query, Path, File et d'autres depuis fastapi, ce sont en réalité des fonctions qui renvoient des classes spéciales.
Astuce
Pour déclarer des fichiers dans le corps de la requête, vous devez utiliser File, sinon les paramètres seraient interprétés comme des paramètres de requête ou des paramètres de corps (JSON).
Les fichiers seront téléversés en « données de formulaire ».
Si vous déclarez le type de votre paramètre de fonction de chemin d'accès comme bytes, FastAPI lira le fichier pour vous et vous recevrez le contenu sous forme de bytes.
Gardez à l'esprit que cela signifie que tout le contenu sera stocké en mémoire. Cela fonctionnera bien pour de petits fichiers.
Mais dans plusieurs cas, vous pourriez bénéficier de l'utilisation d'UploadFile.
Paramètres de fichier avec UploadFile¶
Définissez un paramètre de fichier de type UploadFile :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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):
return {"filename": file.filename}
Utiliser UploadFile présente plusieurs avantages par rapport à bytes :
- Vous n'avez pas besoin d'utiliser
File()comme valeur par défaut du paramètre. - Il utilise un fichier « spooled » :
- Un fichier stocké en mémoire jusqu'à une taille maximale, puis, au-delà de cette limite, stocké sur le disque.
- Cela fonctionne donc bien pour des fichiers volumineux comme des images, des vidéos, de gros binaires, etc., sans consommer toute la mémoire.
- Vous pouvez obtenir des métadonnées à partir du fichier téléversé.
- Il offre une interface
asyncde type file-like. - Il expose un véritable objet Python
SpooledTemporaryFileque vous pouvez passer directement à d'autres bibliothèques qui attendent un objet « file-like ».
UploadFile¶
UploadFile a les attributs suivants :
filename: unestrcontenant le nom de fichier original téléversé (par ex.myimage.jpg).content_type: unestravec le type de contenu (type MIME / type média) (par ex.image/jpeg).file: unSpooledTemporaryFile(un objet de type fichier). C'est l'objet fichier Python réel que vous pouvez passer directement à d'autres fonctions ou bibliothèques qui attendent un objet « file-like ».
UploadFile a les méthodes async suivantes. Elles appellent toutes les méthodes correspondantes du fichier sous-jacent (en utilisant le SpooledTemporaryFile interne).
write(data): écritdata(stroubytes) dans le fichier.read(size): litsize(int) octets/caractères du fichier.seek(offset): se déplace à la position d'octetoffset(int) dans le fichier.- Par ex.,
await myfile.seek(0)irait au début du fichier. - C'est particulièrement utile si vous exécutez
await myfile.read()une fois puis devez relire le contenu.
- Par ex.,
close(): ferme le fichier.
Comme toutes ces méthodes sont async, vous devez les « await ».
Par exemple, à l'intérieur d'une fonction de chemin d'accès async, vous pouvez obtenir le contenu avec :
contents = await myfile.read()
Si vous êtes dans une fonction de chemin d'accès def normale, vous pouvez accéder directement à UploadFile.file, par exemple :
contents = myfile.file.read()
Détails techniques async
Lorsque vous utilisez les méthodes async, FastAPI exécute les méthodes de fichier dans un pool de threads et les attend.
Détails techniques Starlette
L'UploadFile de FastAPI hérite directement de l'UploadFile de Starlette, mais ajoute certaines parties nécessaires pour le rendre compatible avec Pydantic et les autres parties de FastAPI.
Qu'est-ce que les « données de formulaire »¶
La façon dont les formulaires HTML (<form></form>) envoient les données au serveur utilise normalement un encodage « spécial » pour ces données, différent de JSON.
FastAPI s'assure de lire ces données au bon endroit plutôt que depuis JSON.
Détails techniques
Les données des formulaires sont normalement encodées avec le « type de média » application/x-www-form-urlencoded lorsqu'elles n'incluent pas de fichiers.
Mais lorsque le formulaire inclut des fichiers, il est encodé en multipart/form-data. Si vous utilisez File, FastAPI saura qu'il doit récupérer les fichiers depuis la partie appropriée du corps.
Si vous souhaitez en savoir plus sur ces encodages et les champs de formulaire, consultez la MDN Web Docs pour POST.
Alertes
Vous pouvez déclarer plusieurs paramètres File et Form dans un chemin d'accès, mais vous ne pouvez pas également déclarer des champs Body que vous vous attendez à recevoir en JSON, car la requête aura le corps encodé en multipart/form-data au lieu de application/json.
Ce n'est pas une limitation de FastAPI, cela fait partie du protocole HTTP.
Téléversement de fichier facultatif¶
Vous pouvez rendre un fichier facultatif en utilisant des annotations de type standard et en définissant une valeur par défaut à None :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes | None, File()] = None):
if not file:
return {"message": "No file sent"}
else:
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = None):
if not file:
return {"message": "No upload file sent"}
else:
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes | None = File(default=None)):
if not file:
return {"message": "No file sent"}
else:
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = None):
if not file:
return {"message": "No upload file sent"}
else:
return {"filename": file.filename}
UploadFile avec des métadonnées supplémentaires¶
Vous pouvez aussi utiliser File() avec UploadFile, par exemple pour définir des métadonnées supplémentaires :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(
file: Annotated[UploadFile, File(description="A file read as UploadFile")],
):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File(description="A file read as bytes")):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(
file: UploadFile = File(description="A file read as UploadFile"),
):
return {"filename": file.filename}
Téléverser plusieurs fichiers¶
Il est possible de téléverser plusieurs fichiers en même temps.
Ils seraient associés au même « champ de formulaire » envoyé en « données de formulaire ».
Pour cela, déclarez une list de bytes ou d'UploadFile :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.post("/files/")
async def create_files(files: Annotated[list[bytes], File()]):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async def main():
content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
return HTMLResponse(content=content)
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
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]):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async def main():
content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
return HTMLResponse(content=content)
Vous recevrez, comme déclaré, une list de bytes ou d'UploadFile.
Détails techniques
Vous pourriez aussi utiliser from starlette.responses import HTMLResponse.
FastAPI fournit les mêmes starlette.responses sous fastapi.responses simplement pour votre convenance en tant que développeur. Mais la plupart des réponses disponibles proviennent directement de Starlette.
Téléversements multiples avec métadonnées supplémentaires¶
Et de la même manière que précédemment, vous pouvez utiliser File() pour définir des paramètres supplémentaires, même pour UploadFile :
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.post("/files/")
async def create_files(
files: Annotated[list[bytes], File(description="Multiple files as bytes")],
):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async def create_upload_files(
files: Annotated[
list[UploadFile], File(description="Multiple files as UploadFile")
],
):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async def main():
content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
return HTMLResponse(content=content)
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.post("/files/")
async def create_files(
files: list[bytes] = File(description="Multiple files as bytes"),
):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async def create_upload_files(
files: list[UploadFile] = File(description="Multiple files as UploadFile"),
):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async def main():
content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
"""
return HTMLResponse(content=content)
Récapitulatif¶
Utilisez File, bytes et UploadFile pour déclarer des fichiers à téléverser dans la requête, envoyés en « données de formulaire ».